Fragment采坑記錄

  • 1、 bug現(xiàn)象:當(dāng)手機上的app運行的數(shù)量 超過手機清理的上限,即內(nèi)存不足時,應(yīng)用進入后臺再次打開時嵌套的Fragment頁面顯示空白; 問題分析:內(nèi)存不足時,宿主Activity會被異常關(guān)閉,當(dāng)再次打開時,Activity重新創(chuàng)建,但嵌套的Fragment填充發(fā)生了錯亂。

解決問題:復(fù)現(xiàn)bug,會發(fā)現(xiàn)除嵌套的Fragment外,其他的Fragment顯示和點擊事件均正常,也就是說問題可以鎖定在嵌套的Fragment的宿主Fragment。 問題范圍鎖定后,查閱資料,發(fā)現(xiàn)與FragmentManager(Fragment管理類)有關(guān)?;乜创a, 問題在對象FragmentTransaction,發(fā)現(xiàn)宿主Activity和宿主Fragment獲取對象FragmentTransaction的方式均為 getSupportFragmentManager().beginTransaction(),而宿主Fragment需要使用getChildFragmentManager().beginTransaction(), 替換代碼,重新運行,問題解決; 總結(jié):Activity中獲取對象FragmentTransaction,統(tǒng)一使用getSupportFragmentManager().beginTransaction(); Fragment中獲取對象FragmentTransaction,統(tǒng)一使用getChildFragmentManager().beginTransaction()。

補充(語言有些書面難懂,不求甚解者可忽略):關(guān)于getChildFragmentManager() 和 getSupportFragmentManager() getChildFragmentManager()是fragment中的方法, 返回的是管理當(dāng)前fragment內(nèi)部子fragments的manager. getSupportFragmentManager()在activity和fragment中都有. 在activity中, 方法用getSupportFragmentManager(), 返回的是管理activity中fragments的manager. 在fragment中, 還叫g(shù)etSupportFragmentManager(), 返回的是把自己加進來的那個manager. 也即, 如果fragment在activity中, fragment.getFragmentManager()得到的是activity中管理fragments的那個manager. 如果fragment是嵌套在另一個fragment中, fragment.getFragmentManager()得到的是它的parent的getChildFragmentManager(). 總結(jié)就是: getFragmentManager()是本級別管理者, getChildFragmentManager()是下一級別管理者. 這實際上是一個樹形管理結(jié)構(gòu).

  • 2、 bug現(xiàn)象:當(dāng)手機上的app運行的數(shù)量 超過手機清理的上限,即內(nèi)存不足時,應(yīng)用進入后臺再次打開時點擊或者滑動Fragment應(yīng)用閃退。

問題分析:內(nèi)存不足時,宿主Activity會被異常關(guān)閉,當(dāng)再次打開時,Activity重新創(chuàng)建, 但與Viewpager結(jié)合使用的Fragment生命周期異常,viewpager的適配器繼承自FragmentPagerAdapter,頁面雖然被恢復(fù), 但Fragment內(nèi)的數(shù)據(jù)均被回收,所以Fragment會出現(xiàn)空指針。

解決問題:經(jīng)不斷探索目前有兩種解決方案。

第一種,在Fragment集合放入適配器之前, 利用getSupportFragmentManager().getFragments(),獲取到新的List<Fragment>, 然后遍歷并刪除這個集合內(nèi)的所有的Fragment對象, 刪除Fragment對象的代碼:

getSupportFragmentManager().beginTransaction().remove(saveFragmentList.get(i)).commit()。
            List<Fragment> saveFragmentList = getSupportFragmentManager().getFragments();
            for (int i = 0; i < saveFragmentList.size(); i++) {
                getSupportFragmentManager().beginTransaction().remove(saveFragmentList.get(i)).commit();
            }
            list1Fragment = new List1Fragment();
            list2Fragment = new List2Fragment();
            list3Fragment = new List3Fragment();
            list4Fragment = new List4Fragment();
            fragmentList.clear();
            fragmentList.add(list1Fragment);
            fragmentList.add(list2Fragment);
            fragmentList.add(list3Fragment);
            fragmentList.add(list4Fragment);

第二種,解釋起來比較麻煩,代碼比較直觀,直接上代碼。

List<Fragment> saveFragmentList = getSupportFragmentManager().getFragments();
            if (saveFragmentList != null && saveFragmentList.size() > 0) {
                list1Fragment = (List1Fragment) saveFragmentList.get(0);
                list2Fragment = (List2Fragment) saveFragmentList.get(1);
                list3Fragment = (List3Fragment) saveFragmentList.get(2);
                list4Fragment = (List4Fragment) saveFragmentList.get(3);
            } else {
                list1Fragment = new List1Fragment();
                list2Fragment = new List2Fragment();
                list3Fragment = new List3Fragment();
                list4Fragment = new List4Fragment();
            }
            fragmentList.clear();
            fragmentList.add(list1Fragment);
            fragmentList.add(list2Fragment);
            fragmentList.add(list3Fragment);
            fragmentList.add(list4Fragment);

個人比較傾向于第二種。這兩種方法的區(qū)別是,第一種會重新繪制所有相關(guān)的Fragment, 而第二種會保存Activity異常銷毀前的Fragment的展示狀態(tài)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容