Android异常篇 IllegalStateException: Can not perform this action after onSaveInstanceState

一、官方文档解析

public abstract int commit ()

Added in API level 11
Schedules a commit of this transaction. The commit does not happen immediately; it will be scheduled as work on the main thread to be done the next time that thread is ready.

A transaction can only be committed with this method prior to its containing activity saving its state. If the commit is attempted after that point, an exception will be thrown. This is because the state after the commit can be lost if the activity needs to be restored from its state. See commitAllowingStateLoss() for situations where it may be okay to lose the commit.

Returns
Returns the identifier of this transaction’s back stack entry, if addToBackStack(String) had been called. Otherwise, returns a negative number.

commit不是立即执行,而是当主线程在下一次准备好的时候进行修改,也就是说,这个函数只是把请求放到队列中去。

同时,commit操作必须在父容器saving state之前,因为当父容器saving state,意味着父容器可能会被销毁,这个时候这个commit可能会变成无效的。

二、解决方案 - commitAllowingStateLoss()

public abstract int 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.

允许在XXXActivity执行onSaveInstanceState后进行Fragment修改

  public static void showInstance(XXXXActivity activity) {
    
    
        Bundle bundle = new Bundle();
        XXXDialog dialog = new XXXDialog ();
        dialog .setArguments(bundle);

	//  正确方式 :commitAllowingStateLoss()
        FragmentManager supportFragmentManager = activity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        fragmentTransaction.add(dialog ,"XXXTag");
        fragmentTransaction.commitAllowingStateLoss();

	 //   原有导致异常的方式:show() 本质上也是调用commit
     //   dialog.show(activity.getSupportFragmentManager(), "XXXTag");

    }

三、解决方案 - 反射

public class BDialogFragment 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 extends  View> T obtainView(int resId){
    
    
        if(null == rootView){
    
    
            return null;
        }
        return (T) rootView.findViewById(resId);
    }
 
    /**
     * 反射关键方法
     * @param manager
     * @param tag
     */
    @Override
    public void show(FragmentManager manager, String tag) {
    
    
        try{
    
    
            Field dismissed = DialogFragment.class.getDeclaredField("mDismissed");
            dismissed.setAccessible(true);
            dismissed.set(this,false);
        } catch (NoSuchFieldException | IllegalAccessException e) {
    
    
            e.printStackTrace();
        }
 
        try {
    
    
            Field showByMe = DialogFragment.class.getDeclaredField("mShownByMe");
            showByMe.setAccessible(true);
            showByMe.set(this,true);
        } catch (NoSuchFieldException | IllegalAccessException e) {
    
    
            e.printStackTrace();
        }
 
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44720673/article/details/122631525