解决 Can not perform this action after onSaveInstanceState with DialogFragment

异常错误日志

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1323)
    at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1341)
    at android.app.BackStackRecord.commitInternal(BackStackRecord.java:597)
    at android.app.BackStackRecord.commit(BackStackRecord.java:575)
    at android.app.DialogFragment.show(DialogFragment.java:230)
    at com.leo.kang.MainActivity$MyHandler.handleMessage(MainActivity.java:670)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5282)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:810)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)

异常原因

  1. 因为我是在onResume方法中调取了签到接口,然后拿到签单信息,弹出签到窗口,因此可能导致该异常发生。
  2. onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错
  3. 解决方法就是把commit()方法替换成 commitAllowingStateLoss()

api中是这么解释commitAllowingStateLoss()

Like commit() but allows the commit to be executed after an activity's state is saved. 
This is dangerous because the commit can be lost if the activity needs to later be restored 
from its state, so this should only be used for cases where it is okay for the UI state to 
change unexpectedly on the user.

解决方案

继承DialogFragment,复写show()方法

// 注意包名要和support v4中的相同,因为show方法中用到了package的变量mDismissed和mShownByMe
package android.support.v4.app;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by kangyi on 2016-11-21.
 */
public class BaseDialogFragment extends DialogFragment {
    View rootView;

    Context mContext;

    public View getRootView(ViewGroup container, int resId) {
        mContext = getActivity();
        rootView = LayoutInflater.from(mContext).inflate(resId, container, false);
        return rootView;
    }

    public  T obtainView(int resId) {
        if (null == rootView) {
            return null;
        }
        return (T) rootView.findViewById(resId);
    }

    /**
     * Display the dialog, adding the fragment to the given FragmentManager.  This
     * is a convenience for explicitly creating a transaction, adding the
     * fragment to it with the given tag, and committing it.  This does
     * not add the transaction to the back stack.  When the fragment
     * is dismissed, a new transaction will be executed to remove it from
     * the activity.
     * @param manager The FragmentManager this fragment will be added to.
     * @param tag The tag for this fragment, as per
     * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
     */
    @Override
    public void show(FragmentManager manager, String tag) {
        mDismissed = false;
        mShownByMe = true;
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        // 这里吧原来的commit()方法换成了commitAllowingStateLoss()
        ft.commitAllowingStateLoss();
    }
}

后记

多看源码,多记笔记解决问题。

你可能感兴趣的:(解决 Can not perform this action after onSaveInstanceState with DialogFragment)