onStop вызывается после onDestroy? - PullRequest
11 голосов
/ 17 июня 2020

Я столкнулся с довольно странной проблемой с жизненным циклом Activity.

Короткий приквел:

Первый обнаруженный мной симптом - это сбой с IllegalArgumentException, когда я пытался отменить регистрацию приемника в onStop после регистрации его в onStart.

После сброса полного списка активных приемников (некоторые отражающие маги c) я обнаружил что моего ресивера нет в списке. Он либо был удален где-то еще по ошибке, либо был удален во время onDestroy вызова Activity, где Context очищается (во время onDestroy ActivityThread вызовов ContextImpl#performFinalCleanup, который затем вызывает LoadedApk#removeContextRegistrations) .

Что происходит?

После добавления дополнительной аналитической информации в cra sh я обнаружил, что в то время как cra sh происходит в onStop, Activity находится в довольно странном состоянии - это isDestroyed() вызов возвращает true, isFinishing() возвращает false, а getLifecycle().getCurrentState() возвращает DESTROYED ...

Проверка обычного вызова onStop() (без cra sh) показывает, что Activity находится в этом состоянии:

isDestroyed() равно false, а getLifecycle().getCurrentState() равно CREATED в onStop.

Итак, я пришел к выводу, что onStop вызывается после onDestroy, что, как я думал, невозможно, но похоже, что это происходит.

И onStop определенно не вызывается вручную чем-то другим в приложении, так как это трассировка стека, откуда вызывается onStop.

com.myapp.TheActivity.onStop (TheActivity.java:217)
android.app.Instrumentation.callActivityOnStop (Instrumentation.java:1474)
android.app.Activity.performStop (Activity.java:8189)
android.app.ActivityThread.callActivityOnStop (ActivityThread.java:4994)
android.app.ActivityThread.performStopActivityInner (ActivityThread.java:4967)
android.app.ActivityThread.handleStopActivity (ActivityThread.java:5047)
android.app.servertransaction.TransactionExecutor.performLifecycleSequence (TransactionExecutor.java:233)
android.app.servertransaction.TransactionExecutor.cycleToPath (TransactionExecutor.java:201)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:173)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2220)
android.os.Handler.dispatchMessage (Handler.java:107)
android.os.Looper.loop (Looper.java:237)
android.app.ActivityThread.main (ActivityThread.java:8016)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1076)

Ответы [ 2 ]

2 голосов
/ 22 июня 2020

Причина неясна, но в последнее время она привлекает все больше внимания. И это происходит в парах onResume / onPause и onStart / onStop для вызова register / unregister. Что касается этих проверок lifeCycle, убедитесь, что у вас есть Экземпляр активности с hashCode () или что-то в этом роде. В любом случае, чтобы решить эту проблему, лучше всего обернуть вызовы регистрации / отмены регистрации в блоке try / catch:

private void registerBroadcastReceiver() {
    try {
        appUpdateReceiver = new AppUpdateReceiver();
        registerReceiver(appUpdateReceiver, appUpdateIntentFilter);
    } catch (IllegalArgumentException e) {
        // already registered
    }

}

private void unregisterBroadcastReceiver() {
    try {
        unregisterReceiver(appUpdateReceiver);
    } catch (IllegalArgumentException e) {
        // already unregistered
    }
}
1 голос
/ 25 июня 2020

Я не совсем уверен, почему это происходит в первую очередь, но я столкнулся с чем-то похожим на одном из устройств Xiaomi, что не происходило ни на одном из эмуляторов (или моем устройстве), но произошло на чьем-то другом телефоне . onStop() был вызван через 5 секунд после перемещения приложения в фоновый режим, но onPause() был вызван немедленно. Еще более странная проблема: если в промежутке между этими 5 секундами я открываю приложение из диспетчера задач, вызывается onStart(). (Обратите внимание на вызовы 2 onStart(), но не на один вызов onStop().) Я думаю, что было бы возможно, если бы действие было уничтожено, onDestroy() был бы вызван до onStop(). В качестве альтернативы вы можете попытаться переместить вызовы регистрации получателя на onResume() и onPause() вместо onStart() и onStop().

Второе: я точно не использую жизненный цикл действия, когда речь идет о проверке возобновленного или приостановленного состояния, но я бы предложил переопределить все эти методы (onPause, onResume et c ...), сохраняя состояние в логических переменных и регистрируя состояние при проверке фактических вызовов. Возможно, это приведет к другому состоянию, так как это довольно необычная проверка.

Если этого не происходит при других действиях, в этом действии, возможно, что-то отправляет так много обратных вызовов в основной цикл сообщений, что предотвращает onStop() от вызова в первую очередь из-за переполнения, вызывающего возникновение этого исключения. Это, конечно, только предположения, но я был бы признателен, если бы они в чем-то помогли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...