android 为什么fragment在调用hide方法后没有生效_Android 多 Fragment 切换优化
code小生,一個(gè)專(zhuān)注 Android 領(lǐng)域的技術(shù)平臺(tái)
公眾號(hào)回復(fù) Android 加入我的安卓技術(shù)群
作者:DDDong丶
鏈接:https://www.jianshu.com/p/c8e8a0249911
聲明:本文已獲DDDong丶授權(quán)發(fā)表,轉(zhuǎn)發(fā)等請(qǐng)聯(lián)系原作者授權(quán)
問(wèn)題分析
一直在簡(jiǎn)書(shū)里看別人的技術(shù)貼,今天我也來(lái)寫(xiě)點(diǎn)自己的心得!最近在寫(xiě)一個(gè)項(xiàng)目用到大量的Fragment后的總結(jié)!
我想剛剛接觸安卓的同學(xué)或許會(huì)這么寫(xiě):
FragmentManager?fragmentManager=getSupportFragmentManager();FragmentTransaction?fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.add(ViewId,fragment);//?或者fragmentTransaction.replace(ViewId,fragment);
fragmentTransaction.commit();
基礎(chǔ)更好一點(diǎn)的同學(xué)會(huì)用show和hide方法
FragmentManager?fm?=?getSupportFragmentManager();FragmentTransaction?ft?=?fm.beginTransaction();
ft.hide(new?FirstFragment())
????????.show(new?SecondFragment())
????????.commit();
誠(chéng)然這兩種都可以切換Fragment,但是面對(duì)用戶(hù)大量點(diǎn)擊來(lái)回切換,或者你的Fragment本來(lái)就很多,每次都這樣操作,那么很快你的應(yīng)用就會(huì)OOM,就算不崩那也會(huì)異常的卡頓!so why?
當(dāng)我們r(jià)eplace時(shí)發(fā)生了以下的生命周期:
image想想看每次都replace一下!!這世界會(huì)有多美好!!!那么問(wèn)題出在哪?回過(guò)頭看看代碼就會(huì)發(fā)現(xiàn)每次在add/replace或者show/hide都會(huì)new 一個(gè)新的實(shí)例,這就是致命原因!!!!!
廢話(huà)不多說(shuō),亮出我的方法(抽取后的):
?/**?*??Fragment的添加
?*?@param?manager?Fragment管理器
?*?@param?aClass?相應(yīng)的Fragment對(duì)象的getClass
?*?@param?containerId?容器的id
?*?@param?args?需要傳值的話(huà)可將bundle填入??不需要傳值就填null
?*/
protected?void?addFragment(FragmentManager?manager,?Class?extends?BaseFragment>?aClass,?int?containerId,?Bundle?args)?{
????String?tag?=?aClass.getName();
????Logger.d("%s?add?fragment?%s",?TAG,?aClass.getSimpleName());
????Fragment?fragment?=?manager.findFragmentByTag(tag);
????FragmentTransaction?transaction?=?manager.beginTransaction();?//?開(kāi)啟一個(gè)事務(wù)
????if?(fragment?==?null)?{//?沒(méi)有添加
????????try?{
????????????fragment?=?aClass.newInstance();?//?通過(guò)反射?new?出一個(gè)?fragment?的實(shí)例
????????????BaseFragment?baseFragment?=?(BaseFragment)?fragment;?//?強(qiáng)轉(zhuǎn)成我們base?fragment
????????????//?設(shè)置?fragment?進(jìn)入,退出,?彈進(jìn),彈出的動(dòng)畫(huà)
????????????transaction.setCustomAnimations(baseFragment.enter(),?baseFragment.exit(),?baseFragment.popEnter(),?baseFragment.popExit());
????????????transaction.add(containerId,?fragment,?tag);
????????????if?(baseFragment.isNeedToAddBackStack())?{?//?判斷是否需要加入回退棧
????????????????transaction.addToBackStack(tag);?//?加入回退棧時(shí)制定一個(gè)tag,以便在找到指定的事務(wù)
????????????}
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}?else?{
????????if?(fragment.isAdded())?{
????????????if?(fragment.isHidden())?{
????????????????transaction.show(fragment);
????????????}
????????}?else?{
????????????transaction.add(containerId,?fragment,?tag);
????????}
????}
????if?(fragment?!=?null)?{
????????fragment.setArguments(args);
????????hideBeforeFragment(manager,?transaction,?fragment);
????????transaction.commit();
????}
}
/**
?*?除當(dāng)前?fragment?以外的所有?fragment?進(jìn)行隱藏
?*
?*?@param?manager
?*?@param?transaction
?*?@param?currentFragment
?*/
private?void?hideBeforeFragment(FragmentManager?manager,?FragmentTransaction?transaction,?Fragment?currentFragment)?{
????List?fragments?=?manager.getFragments();for?(Fragment?fragment?:?fragments)?{if?(fragment?!=?currentFragment?&&?!fragment.isHidden())?{
????????????transaction.hide(fragment);
????????}
????}
}
略微解釋一下:
先查詢(xún)fragmentManager 所在的activitiy 中是否已經(jīng)添加了這個(gè)fragment
第一步 先從一個(gè)mAdded 的一個(gè)ArrayList遍歷查找,如果找不到再?gòu)?一個(gè) 叫 mActive 的 SparseArray的一個(gè)map里面查找。
注意:
一個(gè) fragment 被 remove 掉后,只會(huì)從 mAdded 里面刪除,不會(huì)從 mActive 里面刪除,只有當(dāng)這個(gè)fragment 所在的 transaction 從回退棧里面移除后才會(huì) 從mActive 刪除
當(dāng)我們add 一個(gè)fragment時(shí) 會(huì)把我們的fragment 添加到 mAdded 里面,不會(huì)添加到 mActive。
只有當(dāng)我們把 transaction 添加到回退棧的時(shí)候,才會(huì)把我們的 fragment 添加到 mActive 里面。所以我們通過(guò) findFragmentByTag 方法查找出來(lái)的 fragment 不一定是被添加到我們的 activity 中。
使用:
代碼比較多,但是我個(gè)人感覺(jué)使用起來(lái)比較方便,而且功能也比較完善,使用的時(shí)候只需要兩行代碼:
HomeFragment1?homeFragment?=?new?HomeFragment1();addFragment(getSupportFragmentManager(),homeFragment.getClass(),R.id.main_body,null);
當(dāng)我們需要傳值的時(shí)候,只需要將準(zhǔn)備好的bundle以參數(shù)的形式填入即可。
我還增加了一個(gè)是否加入回退棧的判斷,用于實(shí)現(xiàn)一些有關(guān)回退棧的需求,實(shí)現(xiàn)這個(gè)功能還需要在BaseFragment中定義一個(gè)方法:
????????return?true;
}
也就這么點(diǎn)內(nèi)容,各位大佬如果看出什么問(wèn)題或者有什么更好的方法,歡迎大家在下方評(píng)論留言。
推薦閱讀
淺談 Activity,Fragment 模塊化封裝
巧用 Fragment,解耦 Android6.0 權(quán)限適配手記
不怕巨人高
就怕巨人還要踩在巨人肩膀上
這樣就很難超越了
總結(jié)
以上是生活随笔為你收集整理的android 为什么fragment在调用hide方法后没有生效_Android 多 Fragment 切换优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 6000毫安以上智能手机_三星超长续航神
- 下一篇: 安卓4.4玩java_Android4.