Статическая переменная инициализация на 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; не могли бы вы уточнить, какой тип вещания вы используете?

Возможно, что входящее намерение может вызвать изменение конфигурации, которое уничтожит и воссоздает Приложение.