友盟页面统计 - 关于Viewpager中的Fragment的生命周期
生活随笔
收集整理的這篇文章主要介紹了
友盟页面统计 - 关于Viewpager中的Fragment的生命周期
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Activity和Fragment各自理論上的生命周期
- Activity的生命周期是較為經(jīng)典也最清晰的,在此不表;
- Fragment從出現(xiàn)到廣泛運(yùn)用也有一段時(shí)間了,其標(biāo)準(zhǔn)生命周期也僅比Activity多出一些流程,如onCreateView();
- Activity和Fragment在實(shí)際編碼中必定是結(jié)合出現(xiàn)的,表現(xiàn)為Activity作為容器,裝載有一個(gè)或若干個(gè)Fragment;
- 裝載多個(gè)Fragment時(shí),經(jīng)常使用TabHost和Viewpager作為載體;
- 在實(shí)際編碼中發(fā)現(xiàn),Activity和Fragment的混合情況里,其生命周期的交叉可能與預(yù)想中有差別;
-
使用如下方式加載Fragment時(shí):
[java] view plaincopy print?- getSupportFragmentManager()??
- ??????.beginTransaction()??
- ??????.add(R.id.fragment_container,?mFragment,?SHARE_PUBLIC_LIST_FRAGMENT_TAG)??
- ??????.commitAllowingStateLoss();??
其onResume和onPause執(zhí)行過(guò)程為:
- Activity - onResume
- Fragment - onResume
- Activity - onPause
- Fragment - onPause
友盟-頁(yè)面統(tǒng)計(jì)要求
- Activity和Fragment共同體頁(yè)面統(tǒng)計(jì)中,需要保證線(xiàn)性不交叉,每個(gè)onPageStart都有一個(gè)onPageEnd配對(duì),
- 如:onPageStart ->onPageEnd-> onPageStart -> onPageEnd -> onPageStart ->onPageEnd
- 這樣才能保證每個(gè)頁(yè)面統(tǒng)計(jì)的正確。
Viewpager中Fragment的生命周期
- ViewPager裝載Fragment一般使用FragmentPagerAdapter或FragmentStatePagerAdapter,同樣借助FragmentManager,在adapter的getItem方法中根據(jù)position制定顯示的fragment
- 由于Viewpager的緩存特點(diǎn),Viewpager啟動(dòng)時(shí)其第一個(gè)Fragment頁(yè)面及待緩存的頁(yè)面都將按順序呢開(kāi)始他們的正常生命周期,走向onResume,即:
- Viewpager所在Activity - onResume
- Fragment1 - onResume
- Fragment2 - onResume
- Fragment3 - onResume
- 由于這若干個(gè)頁(yè)面的生命周期被同時(shí)催化了,影響了我們的單一判斷,即無(wú)法判斷“真正”顯示和消失在使用者眼前的頁(yè)面。
解決方案
- 方案1:設(shè)置Viewpager的緩存機(jī)制,不緩存除當(dāng)前頁(yè)以外的頁(yè)面數(shù)據(jù),所見(jiàn)即所得,離開(kāi)即銷(xiāo)毀;
- 此方案對(duì)需求改動(dòng)較大,且較影響用戶(hù)體驗(yàn);
- 方案2:重載Fragment.onHiddenChanged(boolean hidden)方法,其參數(shù)hidden代表當(dāng)前fragment顯隱狀態(tài)改變時(shí),是否為隱藏狀態(tài),可通過(guò)check此參數(shù)作處理;
- 此方案局限在于本方法的系統(tǒng)調(diào)用時(shí)間發(fā)生在顯隱狀態(tài)改變時(shí),但第一次顯示時(shí)此方法并不調(diào)用;
- 方案3:重載Fragment.setUserVisibleHint(boolean isVisibleToUser)方法,其參數(shù)isVisibleToUser顧名思義最接近我們的需求,代表頁(yè)面是否“真正”對(duì)使用者顯示;
- 此方案局限在于此方法的第一次系統(tǒng)調(diào)用甚至早于Fragment的onCreate方法,故其第一次調(diào)用時(shí)isVisibleToUser值總為false,影響我們對(duì)生命周期順序的判定;
- Fragment1 - isVisibleToUser - false (多余)
- Fragment1 - isVisibleToUser - true
- Fragment1 - isVisibleToUser - false
- Fragment2 - isVisibleToUser - false (多余)
- Fragment2 - isVisibleToUser - true
- Fragment2 - isVisibleToUser - false
實(shí)際采用的解決方案
- 根據(jù)對(duì)產(chǎn)品需求的理解和用戶(hù)體驗(yàn)的統(tǒng)一,選擇在方案3基礎(chǔ)上加以改進(jìn);
-
setUserVisibleHint()方法本身很接近我們的需求,它的局限點(diǎn)我采取了一個(gè)侵入式的解決方式:
[java] view plaincopy print?- protected?boolean?isCreated?=?false;??
- ??
- @Override??
- public?void?onCreate(Bundle?savedInstanceState)?{??
- ????super.onCreate(savedInstanceState);??
- ??
- ????//?...??
- ????isCreated?=?true;??
- }??
- ??
- /**?
- ?*?此方法目前僅適用于標(biāo)示ViewPager中的Fragment是否真實(shí)可見(jiàn)?
- ?*?For?友盟統(tǒng)計(jì)的頁(yè)面線(xiàn)性不交叉統(tǒng)計(jì)需求?
- ?*/??
- @Override??
- public?void?setUserVisibleHint(boolean?isVisibleToUser)?{??
- ????super.setUserVisibleHint(isVisibleToUser);??
- ??
- ????if?(!isCreated)?{??
- ????????return;??
- ????}??
- ??
- ????if?(isVisibleToUser)?{??
- ????????umengPageStart();??
- ????}else?{??
- ????????umengPageEnd();??
- ????}??
- ??
- }??
-
對(duì)onCreate方法結(jié)束的一個(gè)標(biāo)記即可解決問(wèn)題;
-
切記:此標(biāo)記的改變請(qǐng)勿放在Fragment的onActivtyCreate方法中,此方法調(diào)用滯后于setUserVisibleHint的判斷
One more thing
- Viewpager裝載Fragment時(shí)還有另一個(gè)坑,Viewpager的父容器(Activity或Fragment)在顯隱狀態(tài)改變時(shí),如在Activity的onResume和onPause調(diào)用時(shí),并不會(huì)主動(dòng)通知Viewpager內(nèi)的Fragment執(zhí)行其應(yīng)用的生命周期,故我們需要再增加手動(dòng)強(qiáng)制調(diào)用兩次
- 在Activity中查詢(xún)到當(dāng)前的Fragment,并執(zhí)行其內(nèi)方法,需要借助Viewpager,并改寫(xiě)其PagerAdapter;
- 我采用了此文提到的Second Solution:如何獲得ViewPager當(dāng)前顯示的Fragment?
轉(zhuǎn)載于:https://www.cnblogs.com/wangfeng520/p/5805926.html
總結(jié)
以上是生活随笔為你收集整理的友盟页面统计 - 关于Viewpager中的Fragment的生命周期的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HTML5的viewport使用
- 下一篇: 源文件封装为IP的步骤