1. 程式人生 > >ViewPager+Fragment組合的懶載入實現

ViewPager+Fragment組合的懶載入實現

前一篇文章我們介紹了viewpager的預載入特性(這裡作者強烈建議讀下:)

這篇文章我們主要介紹 viewpager懶載入實現

ViewPager+Fragment的搭配在日常開發中也比較常見,下圖為今日頭條app的截圖

ViewPager控制元件有個特有的預載入機制,即預設情況下當前頁面左右兩側的1個頁面會被載入,以方便使用者滑動切換到相鄰的介面時,可以更加順暢的顯示出來,但也會帶來一個問題,耗費使用者多餘的流量,那麼如何避免,那就需要我們實現懶載入。

懶載入                                                                               

所謂的懶載入,其實也就是延遲載入,就是等到該頁面的UI展示給使用者時,再載入該頁面的資料(從網路、資料庫等),而不是依靠ViewPager預載入機制提前載入兩三個,甚至更多頁面的資料.這樣可以提高所屬Activity的初始化速度,也可以為使用者節省流量.而這種懶載入的方式也已經/正在被諸多APP所採用.

如何實現

首先Fragment為我們提供了一個方法setUserVisibleHint(boolean isVisibleToUser),其中的引數isVisibleToUser就是表示該Fragment的UI對於使用者是否可見。

public void setUserVisibleHint(boolean isVisibleToUser) {
        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
                && mFragmentManager != null && isAdded()) {
            mFragmentManager.performPendingDeferredStart(this);
        }
        mUserVisibleHint = isVisibleToUser;
        mDeferStart = mState < STARTED && !isVisibleToUser;
        if (mSavedFragmentState != null) {
            // Ensure that if the user visible hint is set before the Fragment has
            // restored its state that we don't lose the new value
            mSavedUserVisibleHint = mUserVisibleHint;
        }
    }

此方法來設定Fragment的UI對使用者是否可見,當該頁面對使用者可見/不可見時,系統都會回撥此方法。

我們可以重寫此方法,然後根據回撥的isVisibleToUser引數來進行相關的邏輯判斷,以達到懶載入的效果,比如如果isVisibleToUser==true的話表示當前Fragment對使用者可見,此時再去載入頁面資料。

由於ViewPager內會裝載多個Fragment,而這種懶載入機制對於各個Fragment屬於共同操作,因此適合將其抽取到BaseFragment中。             

需要注意一下:                                                                                                                                                            setUserVisibleHint(boolean isVisibleToUser)

方法會多次回撥,而且可能會在onCreateView()方法執行完畢之前回調.如果isVisibleToUser==true,然後進行資料載入和控制元件資料填充,但是onCreateView()方法並未執行完畢,此時就會出現NullPointerException空指標異常。

所以懶載入需滿足兩個條件

  1. onCreateView()方法執行完畢
  2. setUserVisibleHint(boolean isVisibleToUser)方法返回true                                                          

下面給出basefragment的程式碼:

public abstract class BaseFragment extends Fragment {

    //Fragment的View載入完畢的標記
    private boolean isViewCreated;
    //Fragment對使用者可見的標記
    private boolean isUIVisible;

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //fragment的View載入完畢
        isViewCreated = true;
        lazyLoad();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            isUIVisible = true;
            lazyLoad();
        } else {
            isUIVisible = false;
        }
    }

    //定義抽象方法loadData(),具體載入資料的工作,交給子類去完成
    protected abstract void loadData();

    private void lazyLoad() {
        /**
          *這裡進行雙重標記判斷,是因為setUserVisibleHint會多次回撥,並且會在onCreateView執行前回調,
          必須確保onCreateView載入完畢且頁面可見,才載入資料
         */
        if (isViewCreated && isUIVisible) {
            loadData();
            //資料載入完畢,恢復標記,防止重複載入
            isViewCreated = false;
            isUIVisible = false;
        }
       
    }
}

注意:資料載入完畢要恢復標記,防止資料重複載入

總結:

 講到這裡,相信大家對懶載入已經有了一定的瞭解,接下來就運用到我們的專案裡吧!!!

參考:https://www.jianshu.com/p/7a47907f49c2