場(chǎng)景:
- 在最近的項(xiàng)目中有用到這樣的一個(gè)常見(jiàn)的使用場(chǎng)景:Activity內(nèi)包含一個(gè)ViewPager,里面裝了幾個(gè)Fragment,進(jìn)行切換.在第三個(gè)ViewPager中,又做了一個(gè)postDelayed(Runable)實(shí)現(xiàn)自動(dòng)輪播的輪播圖.
- 我想完成這樣的一個(gè)需求:在第三個(gè)Fragment展現(xiàn)在眼前的時(shí)候開(kāi)始自動(dòng)輪播,一旦切換到別的Activity或者Fragment的時(shí)候停止輪播任務(wù).還是可以節(jié)省一點(diǎn)資源的嘛.
嘗試:
-
開(kāi)始我就在第三個(gè)Fragment里面寫(xiě)上:
@Override public void onResume() { super.onResume(); Log.i(TAG, "onResume: "); if (asv !=null) { asv.startAutoScroll();//開(kāi)始輪播 } } @Override public void onPause() { super.onPause(); Log.i(TAG, "onPause: "); if (asv !=null) { asv.stopAutoScroll();//結(jié)束輪播 } }
可是忘記了,Fragment在這里的生命周期調(diào)用并非是我跳轉(zhuǎn)到這個(gè)Fragment時(shí)調(diào)用onResume,我離開(kāi)時(shí)調(diào)用onPause.結(jié)果當(dāng)然是不能完美的開(kāi)始,結(jié)束自動(dòng)輪播了.
-
要解決這個(gè)問(wèn)題先來(lái)復(fù)習(xí)一下在這種情況下,Activity和Fragment的生命周期調(diào)用順序:
1.png
剛剛進(jìn)入Activity并沒(méi)有切換到第三個(gè)Fragment但是它的生命周期已經(jīng)走完了創(chuàng)建的過(guò)程,在Activity的onResume調(diào)用后它就開(kāi)始調(diào)用自己的生命周期方法.已經(jīng)執(zhí)行了onResume方法,當(dāng)然這個(gè)時(shí)候,輪播圖是還沒(méi)有獲取到數(shù)據(jù),準(zhǔn)備好的,自然不能開(kāi)始自動(dòng)輪播,想要切換到第三個(gè)Fragment的時(shí)候才調(diào)用它的onResume是自以為是的.而且在手動(dòng)切換到第三個(gè)Fragment的時(shí)候并沒(méi)有調(diào)用它的常用生命周期方法,停止輪播當(dāng)然也不用想了.(非常用的不了解).
順便貼一下現(xiàn)在按back銷(xiāo)毀Activity的生命周期:
在這個(gè)Activity銷(xiāo)毀的時(shí)候才調(diào)用了Fragment銷(xiāo)毀的生命周期.
- 后面百度到說(shuō)可以調(diào)用void setUserVisibleHint(boolean isVisibleToUser)方法,根據(jù)isVisibleToUser的狀態(tài)來(lái)判斷當(dāng)前Fragment是否正顯示在用戶(hù)面前,起先我了解了一下他的調(diào)用順序,竟然是在Fragment創(chuàng)建完成之前就會(huì)調(diào)用的,沒(méi)有注意到他后面的調(diào)用時(shí)機(jī).便沒(méi)有嘗試,而是采用監(jiān)聽(tīng)ViewPager的onPageSelected方法來(lái)手動(dòng)調(diào)用第三個(gè)Fragment的onResume方法來(lái)開(kāi)始輪播,在跳轉(zhuǎn)到其他Activity的時(shí)候系統(tǒng)調(diào)用第三個(gè)Fragment的onPause停止輪播,雖然有一些效果,但是感覺(jué)不完美.
解決:
-
后來(lái)還是嘗試了一下setUserVisibleHint這個(gè)方法,發(fā)現(xiàn)他的調(diào)用順序如下:
3.png
在首次調(diào)用時(shí),雖然Fragment都還沒(méi)有創(chuàng)建完成,但是isVisibleToUser是false,手動(dòng)切換進(jìn)入的時(shí)候是true,手動(dòng)切換到別的Fragment的時(shí)候也進(jìn)行了調(diào)用flase.如下使用就能夠在切換到這個(gè)Fragment的時(shí)候開(kāi)始輪播,切出去的時(shí)候停止輪播了:
@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (asv == null) { return; } if (isVisibleToUser) { asv.startAutoScroll(); } else { asv.stopAutoScroll(); } }
-
你以為這樣就完了么?開(kāi)始我也這么以為,但是這樣做還是存在一些問(wèn)題:從這個(gè)Fragment進(jìn)入別的Activity的時(shí)候輪播并沒(méi)有停止,一直繼續(xù)著,postDelayed一直都在循環(huán)的發(fā)送.這是我不能接受的.就在不爽之間,忽然靈機(jī)一動(dòng).我又添了幾行代碼,變成了下面這樣:
private boolean mIsVisibleToUser = false; //1.在別的Fragment的時(shí)候mIsVisibleToUser肯定是false,不會(huì)調(diào)用開(kāi)始輪播 //2.在當(dāng)然Fragment的時(shí)候mIsVisibleToUser肯定是true,所有我從這個(gè)Fragment // 進(jìn)入別的Activity又退來(lái)的時(shí)候,就會(huì)開(kāi)始輪播 //3.從別的Fragment進(jìn)入Activity再回來(lái)的時(shí)候觸發(fā)onResume也會(huì)開(kāi)始輪播,因?yàn)? // mIsVisibleToUser在切換到別的Fragment的時(shí)候就已經(jīng)被置為false了 @Override public void onResume() { super.onResume(); if (asv !=null&&mIsVisibleToUser) {//在這里進(jìn)行一下判斷 asv.startAutoScroll(); } } @Override public void onPause() { super.onPause(); if (asv !=null) { asv.stopAutoScroll(); } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); mIsVisibleToUser = isVisibleToUser;//被調(diào)用時(shí)記錄下?tīng)顟B(tài) if (asv == null) { return; } if (isVisibleToUser) { asv.startAutoScroll(); } else { asv.stopAutoScroll(); } }
經(jīng)過(guò)測(cè)試,感覺(jué)上完美的解決了這個(gè)問(wèn)題,做下筆記,以后有沒(méi)有不要太想當(dāng)然,有線索就去嘗試,實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)嘛.
- void 2017-4-7 19:57:08