クラッシュはかなり奇妙なものです。
onStart
には、Activityフィールドに格納されているBroadcastReceiverが登録されています。 onStop
では、このBroadcastReceiverは登録されていません。 BroadcastReceiverが正常に登録されたら、isRegistered
フィールドもtrue
に設定し、レシーバーの登録を解除する前に、このフィールドをチェックして、必要かどうかを確認します
ただし、Crashlyticsではこれが失敗することがあり、Receiver not registered
から発生するAndroid.app.LoadedApk#forgetReceiverDispatcher
メッセージとともにIllegalArgumentException
でアプリ全体がクラッシュすることがわかりました。私がフラグをチェックすることを考えると、どれがかなり奇妙なことでしょう?
登録/登録解除を処理するContextImpl
およびLoadedApk
クラスを調べて、リフレクションに基づく診断を追加した後、さらに不思議になりました。つまり、このようなクラッシュが発生するたびに、既存のContext
からBroadcastReceiver
へのマップを抽出します( ContextImpl.Java:159 および LoadedApk.Javaを参照)。 :1361 )。
登録が正常に解除されると、クラッシュせずに次のようなマップが表示されます。
com.mypackage.myapp.MyAppContext instance -> list of instances that are registered app wide
com.mypackage.myapp.MyActivity1 instance -> list of instances that are registered for Activity1
com.mypackage.myapp.MyActivity2 instance -> list of instances that are registered for Activity2
...
ただし、クラッシュが発生した場合、このマップは次のようになります。
com.mypackage.myapp.MyAppContext instance -> list of instances that are registered app wide
つまり、BroadcastReceiver
を呼び出したことはありませんが、私のunregisterReceiver
が登録されているアクティビティはありません。
それは1つの特定のアクティビティでのみ発生するので、最初の推測では、このアクティビティは何らかの形でリークされ、onDestroy
ライフサイクルが呼び出され、アクティビティエントリがレシーバーマップから削除されます。登録を解除してください。ただし、その場合、onStop
の後にonDestroy
が呼び出されるのはなぜですか?そして、なぜレシーバーリストは完全に空ですか?
そして、それがリークでない場合、何がそのような不可解な行動につながる可能性がありますか?他の誰かがこのような奇妙な出来事を経験し、私を助けることができることを心から願っています。
私はこの方法で実装を行いました:
OnDestroyイベントでレシーバーを解放する
@Override
public void onDestroy() {
// ...releasing more objects
LocalBroadcastManager.getInstance(this).unregisterReceiver(testReceiver);
super.onDestroy();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ... more initializations
initializeBroadcastReceivers();
}
private void initializeBroadcastReceivers()
{
LocalBroadcastManager.getInstance(this)
.registerReceiver(testReceiver,
new IntentFilter("testReceiver"));
}
private BroadcastReceiver testReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// some code
}
};