Статическая переменная инициализация на M, но не на L из-за применения onCreate(), вызываемого более одного раза
У меня есть приложение, которое имеет класс, производный от класса Application, и заметили, что его метод onCreate() вызывается несколько раз. В дополнение к этому значение его статических переменных составляет reset каждый раз, когда вызывается callCreate().
Это поведение происходит только на M, оно не встречается на L. Я пытаюсь выяснить, есть ли его ошибка в M или предполагаемое изменение в M, или существует некоторая фундаментальная неотъемлемая проблема с архитектурой приложения, которая осталась бездействующей и только теперь проявляется с M.
Класс, созданный приложением onCreate(), вызывается всякий раз, когда вызывается широковещательный приемник onReceive().
Несколько экземпляров класса Application НЕ создаются - onCreate() вызывается в одном экземпляре объекта, и тот же контекст приложения присутствует повсюду.
Вот некоторые фрагменты кода, демонстрирующие это наблюдение:
public class MyApplication extends Application
{
public static int debugVal = 5;
public MyApplication ()
{
theApp = this;
}
public void onCreate ()
{
Log.v(TAG, "++++++++++++ onCreate() debugVal: " + debugVal);
debugVal = 10;
....
public class MyBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive (Context context, Intent intent)
{
Log.v(TAG, "onReceive. debugVal: " + MyApplication.debugVal);
...
При запуске на Marshmallow вывод logcat:
831-1412/? I/ActivityManager Start proc 2244:com.company.redacted/u0a86 for broadcast com.company.redacted/com.company.redacted2.MyBroadcastReceiver
2244-2244/? V/MyApplication: ++++++++++ onCreate() debugVal: 5
2244-2244/? V/MyBroadcastReceiver: onReceive. debugVal: 10
...
831-1327/? I/ActivityManager: Start proc 3271.com.company.redacted/u0a86 for broadcast com.company.redacted2/com.company.redacted1.MyBroadcastReceiver
3271-3271/? V/MyApplication: +++++++++++ onCreate() debugVal: 5
....
Посмотрите, как onCreate() вызывается более одного раза, и как debugVal потерял значение 10 во второй раз, когда был вызван вызов onCreate().
Когда тот же .apk работает на Lollipop, второй вызов onCreate() отсутствует.
Журнал L выглядит следующим образом:
768-783/? I/ActivityManager: Start proc 2480:com.company.redacted/u0a84 for broadcast com/company.redacted1/com.company.redacted2/MyBroadcastReceiver
2480-2480/? V/MyApplication: +++++++++++ onCreate() debugVal:5
2480-2480/? V/MyBroadcastReceiver: onReceive. debugVal: 10
....
2480-2480/com.company.redaced1 v/MyBroadcastReceiver: onReceive. debugVal: 10
Я хотел бы знать, что происходит и устранить, но если я не могу, можно будет заменить класс Application некоторым классом singleton, статические переменные которого гарантированно будут безопасными и надежными и будут инициализированы только один раз?
Это предварительно установленное приложение, которое запускается при загрузке (что является одним из намерений, которое прослушивает приемник), и на данный момент не имеет никаких Актив.
Ответы
Ответ 1
Вы говорите, что onCreate() вызывается дважды в том же процессе, но это, вероятно, неверно. Очень возможно, что Marshmallow более агрессивно относится к убийству вашего процесса, либо из-за меньшего объема памяти, либо просто более агрессивного в отношении уничтожения пакетов бездействия (см. этот вопрос для упоминания "пустой № 17" и docs, упоминающих CACHED_EMPTY).
Чтобы проверить, сделайте свой сервис переднего плана, вызвав startForeground с постоянным уведомлением. Если ваши проблемы исчезнут, это означает, что ОС убивает ваш процесс.
В общем, вы не должны полагаться на то, чтобы оставаться в фоновом режиме - сделать инициализацию как можно более ленивым и мелкозернистым, а также сделать фоновые операции, такие как широковещательные приемники, как можно дешевле.
Ответ 2
Обратите внимание, что в сообщениях журналов, которые вы показали, весь процесс перезапускается, и, следовательно, onCreate вызывается снова, вы можете описать, что происходит между этими двумя событиями, или некоторые детали того, что вы делаете, и что может вызвать убийство первого процесса и начало нового?
Ответ 3
Статические переменные являются плохими для состояния удержания. Причина этого в том, что статические переменные не сохраняются на протяжении всего жизненного цикла и запуска/завершения приложений. Обычно вы используете только статические переменные для постоянного состояния. Это означает переменные, которые имеют одно и то же начальное значение или являются константами.
Если значение меняется, оно должно храниться в памяти, например, Prefs.
Что касается того, почему вы получаете несколько вызовов OnCreate; не могли бы вы уточнить, какой тип вещания вы используете?
Возможно, что входящее намерение может вызвать изменение конфигурации, которое уничтожит и воссоздает Приложение.