假设我有一个活动,它注册 BroadcastReceiver 来监听一些独立于活动生命周期的事件。Receiver 可以在 Activity 的 onStart/onStop 或 onResume/onPause 上注册。收到事件后,我想创建并显示一个片段,例如显示事件详细信息。这可行,但有时应用程序会因“IllegalStateException:onSaveInstanceState 后无法执行此操作”而崩溃。
我认为,这可能发生在活动要暂停和停止状态时,已经保存了其内部状态,但 BroadcastReceiver 尚未取消注册,此时出现新的外部事件。
片段管理器将其状态保存在 onSaveInstanceState() 上。根据官方文档,“如果调用,onSaveInstanceState() 将在 onStop() 之前发生。不能保证它是否会在 onPause() 之前或之后发生”。因此,即使我将在 onResume() 上注册接收器并在 onPause() 上取消注册,也不能保证避免 IllegalStateException,因为活动可以在 onPause() 之前保存它的内部状态。
也许,可能的解决方案是覆盖 onSaveInstanceState() 并在此处设置自己的布尔标志,如 mStateSaved。并且,当接收到新事件时,分析此标志:如果已设置,则假定活动将进入暂停-停止状态,并且不启动片段事务。
我很有趣,也许有更好的解决方案。
感谢您的关注!
更新(代码示例,片段):
@Override
protected void onStart() {
super.onStart();
mActionInformer.addObserver( onActionInformerUpdated );
}
@Override
protected void onStop() {
super.onStop();
mActionInformer.deleteObserver( onActionInformerUpdated );
}
Observer onActionInformerUpdated = new Observer() {
@Override
public void update( Observable observable, Object data ) {
TaskEvent event = (TaskEvent) data;
if( event == TaskEvent.START ) {
setSupportProgressBarIndeterminateVisibility( true );
} else {
setSupportProgressBarIndeterminateVisibility( false );
// update ActionBar
invalidateOptionsMenu();
// handle authorisation event
if( event == TaskEvent.AUTH ) {
String msg = mActionInformer.getExtraMessage();
DialogFragment dlg = AuthorisationDialog.newInstance( msg );
dlg.show( getFragmentManager(), "Authorisation" );
}
}
}
};