问题

DialogFragment 在 Activity 中创建后通过 show(fm, tag) ,弹出 Dialog,如下面的代码所示:

1
2
3
MyDialogFragment dialog = new MyDialogFragment(); // 一个自定义的 DialogFragment
dialog.setButtonListener(aListener); // 一个自定义方法,设置一个监听(如某个按钮的回调)
dialog.show(getFragmentManager(), "tag"); // 弹出对话框

点击按钮可以回调 Activity 的 aListener ,但是,如果在对话框存在的情况下旋转屏幕,再怎么点按钮 aLisenter 也不回调了?!

原因

只要理解了Fragment 和 Activity 生命周期就会知道原因其实很简单:

  1. 旋转屏幕时, Activity 将会被重新创建。
  2. Activity“临终”前会在 onSaveInstanceState() 中保存 DialogFragment 的状态( FragmentManagerState );
  3. “复活”后的Activity,在 onCreate() 中会根据 savedInstanceState 所给予的 FragmentManagerState 自动重新实例化 DialogFragment ,并且 show() 出 dialog

流程为:

旋转屏幕-->-Activity.onSaveInstanceState()-->-Activity.onCreate()-->- DialogFragment.show()--|

这个时候的DialogFragment所持有的 aListener 引用当然也不复存在,再点按钮自然也不会收到回调(虽然这个 dialog 看起来跟旋转屏幕之前的没什么两样,但它们是两个实例)

解决办法

  1. 把 Listener变成 Parcelable 对象塞到 Fragment 的 Arguments 中 (不推荐)
  2. 在 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");