Подтвердить что ты не робот

Перезапуск приложения - точка входа в действие

У меня есть приложение, где для точки входа можно указать "login/splash" Activity, где мне нужно предварительно загрузить свежие данные с сервера. Этот SplashActivity объявляется как:

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

в моем AndroidManifest.xml после загрузки данных я сохраняю некоторые данные в своем пользовательском классе Application, и я перехожу к MainActivity.

Я ожидаю, что после того, как мой Application будет остановлен ОС или пользователем (с помощью Force Stop), а затем позже будет перезапущен пользователем, точкой входа моего приложения будет SplashActivity снова НО система пропускает SplashActivity и отображает MainActivity.

ВОПРОС: Это ожидаемое поведение? Если весь процесс остановлен, не следует ли начинать мое приложение с SplashActivity? Можно ли это сделать?

4b9b3361

Ответ 1

На самом деле, есть несколько проблем, которые решаются этим вопросом и некоторые ответы на него:


Чтобы ответить на ваш первоначальный вопрос: "Да, это ожидаемое поведение".

Android рассматривает каждое действие как отдельный автономный объект. Android запоминает состояние действий в стеке задач, и у него нет проблем с убийством вашего процесса (который содержит все ваши действия) всякий раз, когда он захочет, потому что он "знает", что он всегда может восстанавливать ваши действия всякий раз, когда это необходимо. Эта концепция, разумеется, ломается, когда у вас есть сложное приложение, в котором у вас есть зависимости между действиями и/или у вас есть глобальные данные, которые вы храните в классе Application (или аналогичном статическом/одиночном месте).

Когда Android убивает ваш процесс, он запоминает самое верхнее действие в задаче и когда пользователь возвращается к задаче, он воссоздает процесс, а затем воссоздает только самую верхнюю активность в задаче. В вашем случае MainActivity.

В качестве примера, если ваш стек задач выглядит следующим образом:

StartActivity -> ActivityB -> ActivityC -> ActivityD

и ваша задача перейдет на задний план, и Android убьет процесс, когда пользователь вернется к задаче только ActivityD будет воссоздан. Как только ActivityD будет завершен, Android затем воссоздает ActivityC. Как только ActivityC будет завершен, Android заново создаст ActivityB и т.д. Короче говоря, полный стек не воссоздается, когда пользователь возобновляет задачу.

Не существует комбинации настроек манифеста или флагов Intent, которые позволят вам получить поведение, которое вы хотите. Было бы неплохо, если Android предложит что-то подобное, но на данный момент это не так.


Вы можете определить, был ли ваш процесс перезапущен с использованием статической (класс) логической переменной в вашем производном от приложения классе (или в любом другом классе). Эта переменная всегда будет иметь значение false, когда процесс перезагружается, и вы можете затем проверить состояние переменной из любого места и при необходимости повторно инициализировать (перезагрузить свои данные). Затем вы установите для переменной значение true. Он останется true, пока процесс не будет убит и не будет восстановлен, даже если все ваши действия закончатся. Таким образом, вы можете инициализировать только при необходимости.

Вы также можете использовать это как индикатор для перезапуска приложения из SplashScreen. Таким образом, во всех ваших действиях, в onCreate(), вы можете проверить состояние этой логической переменной, и если приложение было перезапущено, вы можете просто перенаправить на SplashScreen следующим образом:

Intent intent = new Intent(this, SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Это завершит все действия в задаче и перезапустит SplashScreen в корне задачи.


Далее, если вы хотите запретить загружать данные каждый раз, когда пользователь возвращается в приложение (когда он был в фоновом режиме и впоследствии убит AndroidOS), вы должны хранить данные, которые вы загружаете в области приватного кеша и использовать это, когда приложение перезапускается. Это предотвращает необходимость повторной загрузки данных, если ваш процесс был убит и перезапущен.


Другим способом борьбы с этим было бы загрузить ваши данные в Сервис. Если в вашем процессе есть Service, то Android с меньшей вероятностью уничтожит ваш процесс. Вам просто нужно убедиться, что вы завершите свой Service, когда пользователь закончит ваше приложение.


Я понимаю, что этот ответ длинный. Надеюсь, вы сможете получить что-то из этого.

Ответ 2

Это можно сделать следующим образом:

1. SplashActivity не будет возникать никаких сомнений каждый раз.

2. Загрузите данные и сохраните чек (boolean), указав, что загрузка выполняется ранее. Вы можете использовать SharedPreferences.

3. Проверьте состояние в следующий раз и сразу начните MainActivity.