DialogFragment異常Fragment already added的原因與解決辦法
DialogFragment異常的表現形式
快速多次點擊按鈕展示DialogFragment彈框,100%復現崩潰
java.lang.IllegalStateException: Fragment already added: XXDialogFragment
DialogFragment異常的發生原因
查看DialogFragment的show方法源碼,發現每次show的時候都會提交一個add fragment的事務。
DialogFragment.java
public void show(FragmentManager manager, String tag) {
this.mDismissed = false;
this.mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}
當快速多次點擊按鈕時,短時間內調用多次show方法,添加多個add事務(add事務A、add事務B等)。然后系統在執行事務隊列時,在執行了addFragment后,發現又要add這個Fragment,即拋出異常:
FragmentManagerImpl.java
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (DEBUG) {
Log.v("FragmentManager", "add: " + fragment);
}
this.makeActive(fragment);
if (!fragment.mDetached) {
if (this.mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized(this.mAdded) {
this.mAdded.add(fragment);
}
fragment.mAdded = true;
...
}
}
DialogFragment異常的解決辦法
既然知道異常的原因是“執行了多次show方法,添加了多個連續的add事務”。那就改寫下show方法,讓add事務不連續,每次add之前都把原來的remove掉。解決代碼如下:
public class ActivityDialogFragment extends DialogFragment {
@Override
public void show(FragmentManager manager, String tag) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
if (manager.isDestroyed())
return;
}
try {
//在每個add事務前增加一個remove事務,防止連續的add
manager.beginTransaction().remove(this).commit();
super.show(manager, tag);
} catch (Exception e) {
//同一實例使用不同的tag會異常,這里捕獲一下
e.printStackTrace();
}
}
}
浙公網安備 33010602011771號