場景:
- 在最近的項目中有用到這樣的一個常見的使用場景:Activity內(nèi)包含一個ViewPager,里面裝了幾個Fragment,進(jìn)行切換.在第三個ViewPager中,又做了一個postDelayed(Runable)實現(xiàn)自動輪播的輪播圖.
- 我想完成這樣的一個需求:在第三個Fragment展現(xiàn)在眼前的時候開始自動輪播,一旦切換到別的Activity或者Fragment的時候停止輪播任務(wù).還是可以節(jié)省一點資源的嘛.
嘗試:
-
開始我就在第三個Fragment里面寫上:
@Override public void onResume() { super.onResume(); Log.i(TAG, "onResume: "); if (asv !=null) { asv.startAutoScroll();//開始輪播 } } @Override public void onPause() { super.onPause(); Log.i(TAG, "onPause: "); if (asv !=null) { asv.stopAutoScroll();//結(jié)束輪播 } }
可是忘記了,Fragment在這里的生命周期調(diào)用并非是我跳轉(zhuǎn)到這個Fragment時調(diào)用onResume,我離開時調(diào)用onPause.結(jié)果當(dāng)然是不能完美的開始,結(jié)束自動輪播了.
-
要解決這個問題先來復(fù)習(xí)一下在這種情況下,Activity和Fragment的生命周期調(diào)用順序:
1.png
剛剛進(jìn)入Activity并沒有切換到第三個Fragment但是它的生命周期已經(jīng)走完了創(chuàng)建的過程,在Activity的onResume調(diào)用后它就開始調(diào)用自己的生命周期方法.已經(jīng)執(zhí)行了onResume方法,當(dāng)然這個時候,輪播圖是還沒有獲取到數(shù)據(jù),準(zhǔn)備好的,自然不能開始自動輪播,想要切換到第三個Fragment的時候才調(diào)用它的onResume是自以為是的.而且在手動切換到第三個Fragment的時候并沒有調(diào)用它的常用生命周期方法,停止輪播當(dāng)然也不用想了.(非常用的不了解).
順便貼一下現(xiàn)在按back銷毀Activity的生命周期:

在這個Activity銷毀的時候才調(diào)用了Fragment銷毀的生命周期.
- 后面百度到說可以調(diào)用void setUserVisibleHint(boolean isVisibleToUser)方法,根據(jù)isVisibleToUser的狀態(tài)來判斷當(dāng)前Fragment是否正顯示在用戶面前,起先我了解了一下他的調(diào)用順序,竟然是在Fragment創(chuàng)建完成之前就會調(diào)用的,沒有注意到他后面的調(diào)用時機(jī).便沒有嘗試,而是采用監(jiān)聽ViewPager的onPageSelected方法來手動調(diào)用第三個Fragment的onResume方法來開始輪播,在跳轉(zhuǎn)到其他Activity的時候系統(tǒng)調(diào)用第三個Fragment的onPause停止輪播,雖然有一些效果,但是感覺不完美.
解決:
-
后來還是嘗試了一下setUserVisibleHint這個方法,發(fā)現(xiàn)他的調(diào)用順序如下:
3.png
在首次調(diào)用時,雖然Fragment都還沒有創(chuàng)建完成,但是isVisibleToUser是false,手動切換進(jìn)入的時候是true,手動切換到別的Fragment的時候也進(jìn)行了調(diào)用flase.如下使用就能夠在切換到這個Fragment的時候開始輪播,切出去的時候停止輪播了:
@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (asv == null) { return; } if (isVisibleToUser) { asv.startAutoScroll(); } else { asv.stopAutoScroll(); } } -
你以為這樣就完了么?開始我也這么以為,但是這樣做還是存在一些問題:從這個Fragment進(jìn)入別的Activity的時候輪播并沒有停止,一直繼續(xù)著,postDelayed一直都在循環(huán)的發(fā)送.這是我不能接受的.就在不爽之間,忽然靈機(jī)一動.我又添了幾行代碼,變成了下面這樣:
private boolean mIsVisibleToUser = false; //1.在別的Fragment的時候mIsVisibleToUser肯定是false,不會調(diào)用開始輪播 //2.在當(dāng)然Fragment的時候mIsVisibleToUser肯定是true,所有我從這個Fragment // 進(jìn)入別的Activity又退來的時候,就會開始輪播 //3.從別的Fragment進(jìn)入Activity再回來的時候觸發(fā)onResume也會開始輪播,因為 // mIsVisibleToUser在切換到別的Fragment的時候就已經(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)用時記錄下狀態(tài) if (asv == null) { return; } if (isVisibleToUser) { asv.startAutoScroll(); } else { asv.stopAutoScroll(); } }
經(jīng)過測試,感覺上完美的解決了這個問題,做下筆記,以后有沒有不要太想當(dāng)然,有線索就去嘗試,實踐是檢驗真理的唯一標(biāo)準(zhǔn)嘛.
- void 2017-4-7 19:57:08

