Fragment配合ViewPager時的OnResume調(diào)用時機(jī)的精準(zhǔn)控制

場景:

  • 在最近的項目中有用到這樣的一個常見的使用場景: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的生命周期:

2.png

在這個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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容