看這篇文章前锁摔,大家應(yīng)該先對(duì)setMaxLifecycle有所了解庇谆。
本文基于 https://github.com/JantHsueh/Fragmentation 維護(hù)的1.0.5進(jìn)行修改,1.0.6后續(xù)會(huì)補(bǔ)上
上年年末,谷歌為新版本的Fragment
添加了控制其在ViewPager
中的生命周期的新方式——setMaxLifecycle
(而ViewPager2
中默認(rèn)且只有這個(gè)方式)蓬网。
聽說后面還要把
onActivityCreated
砍了螟碎,注意下诞丽。setMaxLifecycle
的添加鲸拥,簡(jiǎn)化了ViewPager
在切換對(duì)Fragment
可見性判斷的復(fù)雜度,但是也增加了一些操X的問題:如果你使用了ViewPager
的setMaxLifecycle
僧免。因?yàn)樯芷诟淖兞诵谈希愕某绦蚩赡芤龀鱿鄳?yīng)的適配。
如果剛好你在用Fragmentation懂衩,又碰上了ViewPager
的setMaxLifecycle
撞叨,那么你就會(huì)發(fā)現(xiàn)只要打開了ViewPager所屬的頁面,ViewPager
容器內(nèi)的所有Fragment
都會(huì)立刻調(diào)用了supportVisible()
可見可見函數(shù)勃痴,無論這些Fragment
是不是都顯示了谒所。當(dāng)然,onLazyInitView
懶加載也被調(diào)用了沛申。
目前我所知道有三種解決辦法,分享下
1姐军、找作者或者接手Fragmentation
項(xiàng)目的大佬解決這個(gè)問題铁材。
2、自己動(dòng)手豐衣足食
3奕锌、用回ViewPager
的BEHAVIOR_SET_USER_VISIBLE_HINT
方法這么多著觉,足足有三個(gè),我們來用下排除法找答案惊暴。
第一個(gè)呢饼丘,我也提了issue了,就看接手大佬能不能看到了辽话。
第二個(gè)呢肄鸽,需要自己download整個(gè)項(xiàng)目下來改,下文會(huì)講
第三個(gè)呢油啤,如果你用的ViewPager1
典徘,這可能就是換個(gè)Adapter
或者改個(gè)參數(shù)的事,如果你用的是ViewPager2
益咬,那你的工作量可能就有一點(diǎn)了逮诲,你自己掂量下,反正我是覺得ViewPager2
不錯(cuò)。
怎么改嘛
注意:這個(gè)修改梅鹦,我會(huì)直接棄用onActivityCreated裆甩,而使用onStart和onResume來判斷Fragment是否處于活躍或顯示狀態(tài),即在onResume后再調(diào)用supportVisible齐唆,請(qǐng)注意檢查你的項(xiàng)目中業(yè)務(wù)邏輯順序是否有需要調(diào)整
1嗤栓、從Fragmentation
下載這個(gè)庫,并導(dǎo)入到你的項(xiàng)目中
2抛腕、從我fork的https://github.com/Ubitar/Fragmentation的fragmentation_core庫中找到下方這3個(gè)文件:VisibleDelegate
、SupportFragmentDelegate
媒殉,以及BaseSupportFragment
文件担敌,并覆蓋你項(xiàng)目中對(duì)應(yīng)的文件。
3廷蓉、然后全封,沒了,你們引用這個(gè)本地庫測(cè)試下吧桃犬,不要忘記把舊的fragmentation_core
依賴去除
源碼修改解析
分析內(nèi)容
1刹悴、打開BaseSupportFragment
,可以看到里面幾乎所有的方法都是通過SupportFragmentDelegate
代理的攒暇,有了解過Fragment
或者Activity
源碼的人都知道這很Android土匀。從SupportFragmentDelegate
源碼中搜索onSupportVisible
函數(shù),發(fā)現(xiàn)是空的形用。
BaseSupportFragment
再次搜索onSupportVisible
的引用就轧,找到了調(diào)用其的VisibleDelegate
類2、在
VisibleDelegate
中順著Fragment
的生命周期去找有關(guān)分發(fā)可見性或直接控制可見性的函數(shù)田度。首先onCreate
和onResume
方法是可以排除的妒御,在剩下的其他函數(shù)onActivityCreated()中可以找到有一個(gè)關(guān)于控制可見性的函數(shù),initVisible()
镇饺。3乎莉、調(diào)查下
initVisible()
isFragmentVisible()
很可疑,跟蹤奸笤。
就那么一句話惋啃,是真正判斷可見性的函數(shù)了。
那么我們寫個(gè)ViewPager
運(yùn)行下揭保,調(diào)試看到fragment.getUserVisibleHint()
在使用setMaxLifecycle
的情況下無論如何都是true
肥橙,所以當(dāng)ViewPager活躍時(shí),上面所有Fragment都被認(rèn)定為可見了秸侣,后面的onLazyInitView()
也自然被調(diào)用了存筏。
4宠互、但是,先別急著修改isFragmentVisible()
椭坚,由于使用了setMaxLifecycle
的緣故予跌,需要把onActivityCreated()
中的內(nèi)容遷移到onStart()
中,遺棄onActivityCreated()
BaseSupportFragment
和SupportFragmentDelegate
也要做出響應(yīng)的修改券册,具體修改內(nèi)容MySupportFragment、SupportFragmentDelegate 垂涯,注意烁焙,多了個(gè) onViewStateRestored()
5、現(xiàn)在回頭改
isFragmentVisible()
耕赘,既然setMaxLifecycle
是通過onResume
來通知可見性的骄蝇,那這里就是缺少了一個(gè)fragment.isResumed()
。isResumed()
都是管用的例如這里的isResumed()
恒定是false
的isFragmentVisible
分為isFragmentVisibleOnResume()
和isFragmentVisibleOnPause()
isFragmentVisible()
補(bǔ)充:
可能我的描述不夠直觀九火,https://github.com/Ubitar/Fragmentation 還是show me the code 最好,我沒有改Fragmentation
的demo册招,僅僅修改了其core
疑問
1岔激、怎么沒有兼容setUserVisibleHint
版本,直接跳setMaxLifecycle
了是掰?
額虑鼎。我沒有寫,這個(gè)需要你看懂setMaxLifecycle
的兼容后键痛,再回去把舊的代碼還原回來(onActivityCreated
和isFragmentVisible
之類)震叙,通過自己設(shè)置的Boolean
值來控制是否兼容setMaxLifecycle
。