DialogFragment的Listener在屏幕旋转后被重置的问题
问题
DialogFragment 在 Activity 中创建后通过 show(fm, tag)
,弹出 Dialog,如下面的代码所示:
1 | MyDialogFragment dialog = new MyDialogFragment(); // 一个自定义的 DialogFragment |
点击按钮可以回调 Activity 的 aListener
,但是,如果在对话框存在的情况下旋转屏幕,再怎么点按钮aLisenter
也不回调了?!
原因
只要理解了Fragment 和 Activity 生命周期就会知道原因其实很简单:
- 旋转屏幕时,
Activity
将会被重新创建。 - Activity“临终”前会在
onSaveInstanceState()
中保存DialogFragment
的状态(FragmentManagerState
); - “复活”后的Activity,在
onCreate()
中会根据savedInstanceState
所给予的FragmentManagerState
自动重新实例化DialogFragment
,并且show()
出 dialog
流程为:
旋转屏幕-->-Activity.onSaveInstanceState()-->-Activity.onCreate()-->- DialogFragment.show()--|
这个时候的DialogFragment所持有的aListener
引用当然也不复存在,再点按钮自然也不会收到回调(虽然这个 dialog 看起来跟旋转屏幕之前的没什么两样,但它们是两个实例)
解决办法
- 把 Listener变成 Parcelable 对象塞到 Fragment 的 Arguments 中(不推荐)
- 在 Activity 的 onCreate() 中 通过 FragmentManager 找到重新实例化的 DialogFragment,重新设置一次 Listener
至于第一种办法,主要是将 Listener 实现 Parcelbale 即可,略~~(就是懒
第二种办法:
@Override
protected void onCreate(Bundle savedInstanceState) {
// call super first !
super.onCreate(savedInstanceState);
// find MyDialogFragment
if(savedInstanceState != null){
MyDialogFragment dialog = (MyDialogFragment) getFragmentManager()
.findFragmentByTag("dialog");
if(dialog != null)
dialog.setButtonListener(aListener);
}
// ...
setContentView(...);
}
具体实例代码见:https://github.com/yrom/sample-dialogfragment-listener