天天看點

關于Fragment的IllegalStateException的部分經驗

項目上線以後,總是要看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。