DialogFragment 寫 setRetainInstance(true);activity重建後不能保持彈出的原因

在DialogFragment 的子類中,調用

  public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 保存整個實例
        setRetainInstance(true);
    }

期望結果是 彈出dialog,在屏幕旋轉後,保持彈出狀態,
但是未彈出,原因是

Dialog

 public void dismiss() {
        if (Looper.myLooper() == mHandler.getLooper()) {
            dismissDialog();
        } else {
            mHandler.post(mDismissAction);
        }
    }
 void dismissDialog() {
        ...
         sendDismissMessage();
         ...
   }
  // 使用handler調用onDismiss
 private void sendDismissMessage() {
        if (mDismissMessage != null) {
            // Obtain a new message so this dialog can be re-used
            Message.obtain(mDismissMessage).sendToTarget();
        }
    }

屏幕旋轉後,looper執行 ReLaunchActivity,在ReLaunchActivity中執行
fragment的onDestroyView(),而DialogFragment 中

 @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mDialog != null) {
            // Set removed here because this dismissal is just to hide
            // the dialog -- we don't want this to cause the fragment to
            // actually be removed.
            mViewDestroyed = true;
            mDialog.dismiss();
            mDialog = null;
        }
    }

執行了 mDialog.dismiss();mDialog向looper發送message,
當ReLaunchActivity執行完之後,fragment attath到acitivity中,然後Looper執行下一個msg,就執行到
DialogFragment 的onDismiss中,而在
DialogFragment 中,調用了 dismissInternal(true);

 @Override
    public void onDismiss(DialogInterface dialog) {
        if (!mViewDestroyed) {
            // Note: we need to use allowStateLoss, because the dialog
            // dispatches this asynchronously so we can receive the call
            // after the activity is paused.  Worst case, when the user comes
            // back to the activity they see the dialog again.
            dismissInternal(true);
        }
    }

dismissInternal 又調用了remove,DialogFragment 又從activity中移除,所以,dialog不會保持彈出狀態
解決辦法:
重寫DialogFragment 的onDismiss方法

@Override
    public void onDismiss(DialogInterface dialog) {
        LegoLog.d("dialog onDismiss");
    }

但是不建議這樣做,還是不要使用 setRetainInstance(true);的方式,因爲會導致內存泄漏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章