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空指標異常。
所以懶載入需滿足兩個條件
onCreateView()
方法執行完畢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;
}
}
}
注意:資料載入完畢要恢復標記,防止資料重複載入
總結:
講到這裡,相信大家對懶載入已經有了一定的瞭解,接下來就運用到我們的專案裡吧!!!