Fragment全解析系列(二):正確的使用姿勢

Fragment系列文章:
1、Fragment全解析系列(一):那些年踩過的坑
2、Fragment全解析系列(二):正確的使用姿勢
3猴鲫、Fragment之我的解決方案:Fragmentation

本篇主要介紹一些Fragment使用技巧澜术。


Fragment是可以讓你的app縱享絲滑的設(shè)計(jì),如果你的app想在現(xiàn)在基礎(chǔ)上性能大幅度提高装处,并且占用內(nèi)存降低,同樣的界面Activity占用內(nèi)存比Fragment要多,響應(yīng)速度Fragment比Activty在中低端手機(jī)上快了很多穴亏,甚至能達(dá)到好幾倍!如果你的app當(dāng)前或以后有移植平板等平臺(tái)時(shí)重挑,可以讓你節(jié)省大量時(shí)間和精力嗓化。


簡陋的目錄
1、一些使用建議
2谬哀、add(), show(), hide(), replace()的那點(diǎn)事
3刺覆、關(guān)于FragmentManager你需要知道的
4、使用FragmentPagerAdapter+ViewPager的注意事項(xiàng)
5史煎、是使用單Activity+多Fragment的架構(gòu)谦屑,還是多模塊Activity+多Fragment的架構(gòu)?


作為一個(gè)穩(wěn)定的app篇梭,從后臺(tái)且回到前臺(tái)氢橙,一定會(huì)在任何情況都能恢復(fù)到離開前的頁面,并且保證數(shù)據(jù)的完整性恬偷。

如果你沒看過本系列的第一篇悍手,為了方便后面文章的介紹,先規(guī)定一個(gè)“術(shù)語”,安卓app有一種特殊情況坦康,就是 app運(yùn)行在后臺(tái)的時(shí)候竣付,系統(tǒng)資源緊張的時(shí)候?qū)е掳補(bǔ)pp的資源全部回收(殺死app的進(jìn)程),這時(shí)把a(bǔ)pp再從后臺(tái)返回到前臺(tái)時(shí)滞欠,app會(huì)重啟古胆。這種情況下文簡稱為:“內(nèi)存重啟”。(屏幕旋轉(zhuǎn)等配置變化也會(huì)造成當(dāng)前Activity重啟筛璧,本質(zhì)與“內(nèi)存重啟”類似)
<h1 id="1"> 1逸绎、一些使用建議 </h1>

1、對Fragment傳遞數(shù)據(jù)隧哮,建議使用setArguments(Bundle args)桶良,而后在onCreate中使用getArguments()取出,在 “內(nèi)存重啟”前沮翔,系統(tǒng)會(huì)幫你保存數(shù)據(jù)陨帆,不會(huì)造成數(shù)據(jù)的丟失。和Activity的Intent恢復(fù)機(jī)制類似采蚀。

2疲牵、使用newInstance(參數(shù)) 創(chuàng)建Fragment對象,優(yōu)點(diǎn)是調(diào)用者只需要關(guān)系傳遞的哪些數(shù)據(jù)榆鼠,而無需關(guān)心傳遞數(shù)據(jù)的Key是什么纲爸。

3、如果你需要在Fragment中用到宿主Activity對象妆够,建議在你的基類Fragment定義一個(gè)Activity的全局變量识啦,在onAttach中初始化,這不是最好的解決辦法神妹,但這可以有效避免一些意外Crash颓哮。詳細(xì)原因參考第一篇的“getActivity()空指針”部分。

protected Activity mActivity;
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    this.mActivity = activity;
}

<h1 id="2">2鸵荠、add(), show(), hide(), replace()的那點(diǎn)事</h1>
1冕茅、區(qū)別
show()hide()最終是讓Fragment的View setVisibility(true還是false)蛹找,不會(huì)調(diào)用生命周期姨伤;

replace()的話會(huì)銷毀視圖,即調(diào)用onDestoryView庸疾、onCreateView等一系列生命周期乍楚;

add()replace()不要在同一個(gè)階級的FragmentManager里混搭使用。

2届慈、使用場景
如果你有一個(gè)很高的概率會(huì)再次使用當(dāng)前的Fragment炊豪,建議使用show()凌箕,hide()拧篮,可以提高性能词渤。

在我使用Fragment過程中,大部分情況下都是用show()串绩,hide()缺虐,而不是replace()

注意:如果你的app有大量圖片礁凡,這時(shí)更好的方式可能是replace高氮,配合你的圖片框架在Fragment視圖銷毀時(shí),回收其圖片所占的內(nèi)存顷牌。

3剪芍、onHiddenChanged的回調(diào)時(shí)機(jī)
當(dāng)使用add()+show(),hide()跳轉(zhuǎn)新的Fragment時(shí)窟蓝,舊的Fragment回調(diào)onHiddenChanged()罪裹,不會(huì)回調(diào)onStop()等生命周期方法,而新的Fragment在創(chuàng)建時(shí)是不會(huì)回調(diào)onHiddenChanged()运挫,這點(diǎn)要切記状共。

4、Fragment重疊問題
使用show()谁帕,hide()帶來的一個(gè)問題就是峡继,如果你不做任何額外處理,在“內(nèi)存重啟”后匈挖,F(xiàn)ragment會(huì)重疊碾牌;(該BUG在support-v4 24.0.0+以上 官方已修復(fù))

有些小伙伴可能就是為了避免Fragment重疊問題,而選擇使用replace()儡循,但是使用show()舶吗,hide()時(shí),重疊問題很簡單解決的:

<h1 id="3">3踊赠、關(guān)于FragmentManager你需要知道的</h1>
FragmentManager棧視圖:
(1)每個(gè)Fragment以及宿主Activity(繼承自FragmentActivity)都會(huì)在創(chuàng)建時(shí),初始化一個(gè)FragmentManager對象每庆,處理好Fragment嵌套問題的關(guān)鍵筐带,就是理清這些不同階級的棧視圖。

下面給出一個(gè)簡要的關(guān)系圖

棧關(guān)系圖.png

(2)對于宿主Activity缤灵,getSupportFragmentManager()獲取的FragmentActivity的FragmentManager對象;

對于Fragment伦籍,getFragmentManager()是獲取的是父Fragment(如果沒有蓝晒,則是FragmentActivity)的FragmentManager對象,而getChildFragmentManager()是獲取自己的FragmentManager對象帖鸦。

<h1 id="4">4芝薇、使用FragmentPagerAdapter+ViewPager的注意事項(xiàng)</h1>

  • 使用FragmentPagerAdapter+ViewPager時(shí),切換回上一個(gè)Fragment頁面時(shí)(已經(jīng)初始化完畢)作儿,不會(huì)回調(diào)任何生命周期方法以及onHiddenChanged()洛二,只有setUserVisibleHint(boolean isVisibleToUser)會(huì)被回調(diào),所以如果你想進(jìn)行一些懶加載攻锰,需要在這里處理晾嘶。

  • 在給ViewPager綁定FragmentPagerAdapter時(shí),
    new FragmentPagerAdapter(fragmentManager)的FragmentManager娶吞,一定要保證正確垒迂,如果ViewPager是Activity內(nèi)的控件,則傳遞getSupportFragmentManager()妒蛇,如果是Fragment的控件中机断,則應(yīng)該傳遞getChildFragmentManager()。只要記住ViewPager內(nèi)的Fragments是當(dāng)前組件的子Fragment這個(gè)原則即可材部。

  • 你不需要考慮在“內(nèi)存重啟”的情況下毫缆,去恢復(fù)的Fragments的問題,因?yàn)镕ragmentPagerAdapter已經(jīng)幫我們處理啦乐导。

<h1 id="5">5苦丁、是使用單Activity+多Fragment的架構(gòu),還是多模塊Activity+多Fragment的架構(gòu)物臂?</h1>
單Activity+多Fragment:
一個(gè)app僅有一個(gè)Activity旺拉,界面皆是Frament,Activity作為app容器使用棵磷。

優(yōu)點(diǎn):性能高蛾狗,速度最快。參考:新版知乎 仪媒、google系app

缺點(diǎn):邏輯比較復(fù)雜沉桌,尤其當(dāng)Fragment之間聯(lián)動(dòng)較多或者嵌套較深時(shí),比較復(fù)雜算吩。

多模塊Activity+多Fragment:
一個(gè)模塊用一個(gè)Activity留凭,比如
1、登錄注冊流程:
LoginActivity + 登錄Fragment + 注冊Fragment + 填寫信息Fragment + 忘記密碼Fragment
2偎巢、或者常見的數(shù)據(jù)展示流程:
DataActivity + 數(shù)據(jù)列表Fragment + 數(shù)據(jù)詳情Fragment + ...

優(yōu)點(diǎn):速度快蔼夜,相比較單Activity+多Fragment,更易維護(hù)压昼。

我的觀點(diǎn):
權(quán)衡利弊求冷,我認(rèn)為多模塊Activity+多Fragment是最合適的架構(gòu)瘤运,開發(fā)起來不是很復(fù)雜,app的性能又很高效匠题。

當(dāng)然拯坟。Fragment只是官方提供的靈活組件,請優(yōu)先遵從你的項(xiàng)目設(shè)計(jì)梧躺!真的特別復(fù)雜的界面似谁,或者單個(gè)Activity就可以完成一個(gè)流程的界面,使用Activity可能是更好的方案掠哥。

最后

如果你讀完了第一篇和這篇文章,那么我相信你使用多模塊Activity+多Fragment的架構(gòu)所遇到的坑秃诵,大部分都應(yīng)該能找到解決辦法续搀。

但是如果流程較為復(fù)雜,比如Fragment A需要啟動(dòng)一個(gè)新的Fragment B并且關(guān)閉當(dāng)前A,或者A啟動(dòng)B菠净,B在獲取數(shù)據(jù)后禁舷,想在返回到A時(shí)把數(shù)據(jù)交給A(類似Activity的startActivityForResult),又或者你保證在Fragment轉(zhuǎn)場動(dòng)畫的情況下毅往,使用pop(tag\id)從棧內(nèi)退出多個(gè)Fragment牵咙,或者你甚至想Fragment有一個(gè)類似Activity的SingleTask啟動(dòng)模式,那么你可以參考下一篇攀唯,我的解決方案庫洁桌,Fragmentation。它甚至提供了一個(gè)讓你在開發(fā)時(shí)侯嘀,可以隨時(shí)查看所有階級的棧視圖的UI界面另凌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市戒幔,隨后出現(xiàn)的幾起案子吠谢,更是在濱河造成了極大的恐慌,老刑警劉巖诗茎,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件工坊,死亡現(xiàn)場離奇詭異,居然都是意外死亡敢订,警方通過查閱死者的電腦和手機(jī)王污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枢析,“玉大人玉掸,你說我怎么就攤上這事⌒讶” “怎么了司浪?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵泊业,是天一觀的道長。 經(jīng)常有香客問我啊易,道長吁伺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任租谈,我火速辦了婚禮篮奄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘割去。我一直安慰自己窟却,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布呻逆。 她就那樣靜靜地躺著夸赫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咖城。 梳的紋絲不亂的頭發(fā)上茬腿,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天,我揣著相機(jī)與錄音宜雀,去河邊找鬼切平。 笑死,一個(gè)胖子當(dāng)著我的面吹牛辐董,可吹牛的內(nèi)容都是我干的悴品。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼郎哭,長吁一口氣:“原來是場噩夢啊……” “哼他匪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夸研,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤邦蜜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后亥至,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悼沈,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年姐扮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了絮供。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茶敏,死狀恐怖壤靶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惊搏,我是刑警寧澤贮乳,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布忧换,位于F島的核電站,受9級特大地震影響向拆,放射性物質(zhì)發(fā)生泄漏亚茬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一浓恳、第九天 我趴在偏房一處隱蔽的房頂上張望刹缝。 院中可真熱鬧,春花似錦颈将、人聲如沸梢夯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厨疙。三九已至,卻和暖如春疑务,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梗醇。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工知允, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叙谨。 一個(gè)月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓温鸽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親手负。 傳聞我的和親對象是個(gè)殘疾皇子涤垫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容