在使用DialogFragment的show时,会发生一些异常,整理一下。
1、重复添加的异常
java.lang.IllegalStateException: Fragment already added
2、状态相关的异常
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
带着问题来看看DialogFragment源码中的show做了什么:
/**
* 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
* <em>not</em> 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}.
*/
public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}
源码中的show方法很简单,所以原因也很明显:
- 由于直接使用 FragmentTransaction 的
add()
方法,所以会出现重复添加; - 由于使用的是 FragmentTransaction 的
commit()
,而不是commitAllowingStateLoss()
,所以会出现状态问题的异常。(之前记得有分析过commit与commitAllowingStateLoss的区别 android Fragment的commit与commitAllowingStateLoss )
问题修复
重写DialogFragment的show(),如下:
@Override
public void show(FragmentManager manager, String tag) {
//避免重复添加的异常 java.lang.IllegalStateException: Fragment already added
Fragment fragment = manager.findFragmentByTag(tag);
if (fragment != null) {
FragmentTransaction fragmentTransaction = manager.beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commitAllowingStateLoss();
}
//避免状态丢失的异常 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
try {
super.show(manager, tag);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
当然也可以通过反射来调用 commitAllowingStateLoss()
,只是复杂度比较高,不是很必要。
网友评论