項目上線以後,總是要看Bugly上的崩潰統計。最近發現有一個
java.lang.IllegalStateException
Fragment already added:
連續出現了很多次。看了Bugly上的崩潰提示,
1. 該異常表示fragment已經被添加過,通常是因為重複添加fragment導緻的,建議調用FragmentTransaction.add方法,先判斷fragment.isAdded()。
[解決方案]:以下是參考解決方案:
if (fragment.isAdded()) {
fragmentManager.beginTransaction().show(fragment).commit();
} else {
fragmentManager.beginTransaction().remove(fragment).commit();
frament = new Fragment();
fragmentManager.beginTransaction().add(R.id.layout_frame, fragment).commit();
}
2. 該異常還經常發生在使用DialogFragment的場景下,DialogFragment也是Fragment的一個子類,其show()方法等同于FragmentTransaction.add()方法,dismiss()方法等同于FragmentTransaction.remove()方法。是以發生異常的原因同上。解決方案如下:
if (dialogFragment.isAdded())
dialogFragment.dismiss();
else
dialogFragment.show();
解決過程如下:
然後,我閱讀我的代碼,然後又跑了APP,再仔細看了錯誤提示,想到了可能是使用者快速點選一個按鈕,然後調用了多次,dialogfragment的show方法。這樣就會導緻fragment被多次添加。這時候隻需要在show的時候 增加判斷就可以了。
其實是個很簡單的bug,我想分享的是,有時候我們認為不會出現的Bug出現了,那就要考慮到 使用者是否是正常使用的。明明一個按鈕 點選一次就可以了,卻有使用者連續點選,就像我們給使用者提示toast的時候,一般都會做一個保護,防止使用者多次點選,連續彈相同的提示。那麼我們的按鈕也需要做同樣的保護,比如部分功能按鈕,我們做一個防止連續點選的保護。如,擷取驗證碼,某些開關按鈕等。
1.分享一個按鈕連續點選的功能,我們可以通過Handler來做一個延遲消息。
private Handler handler = new Handler();
public void controlViewClickable(final View view, long delay) {
// 如果已經是不可點選,就不點選
if(null == view || !view.isClickable())
return;
view.setClickable(false);
handler.postDelayed(new Runnable() {
@Override
public void run() {
view.setClickable(true);
}
},delay);
}
2.借着這次看fragment的時候,順便看了一下FragmentStatePagerAdapter和FragmentPagerAdapter的差別。
相對性能來說,FragmentStatePagerAdapter比較有優勢,它有一個setOffscreenPageLimit()的方法,可以設定緩存頁面的數量。加載的Fragment的數量超過了設定的值,則會回收掉多餘的頁面。在我們需要的時候,重新加載一個Fragment。
而FragmentPagerAdapter,會把所有的Fragment都儲存下來。不會自動去回收。當然,重新回到該頁面就會很快,不用消耗流量去重新加載了。
一般使用的時候,頁面較少則使用FragmentPagerAdapter。