Android優化--Fragment懶載入

weixin_34138377發表於2018-09-28

一.使用原因

        在android應用中,ViewPager是我們不可避免使用的一個控制元件,因為它可以使我們在佔用較少空間的同時,增加內容的豐富性。但是,假如ViewPager的每一個Fragment都需要通過網路拉去資料載入,而ViewPager是預設載入前兩項的,所以在很容易造成網路丟包或者網路堵塞等問題,所以Fragment使用懶載入是非常有必要的。

        通俗點說,當使用viewpager+adapter作為應用大的佈局時,viewpager會通過setOffscreenPageLimit來設定預載入的專案,不設定setOffscreenPageLimit,則預設為1(設定0無效,下面有原始碼),也就是當我們開啟應用看到fragmentOne的時候,實際上其他的fragment也進行了載入(這裡載入的數量主要看你設定的setOffscreenPageLimit的大小),只不過這幾個fragment沒有顯示出來罷了,但是這樣就會造成不必要的資源浪費(比如fragmentSecond沒有顯示,但是卻進行了大量的網路操作)。

        懶載入的作用就是隻載入當前顯示的頁面且只載入一次,滑動到其他頁面時才載入其他頁面資料,當再滑動到已載入過資料的頁面時不再進行資料載入操作,如果想重新整理資料,再呼叫相應的載入資料方法就好了。

14093317-0c93269b7549799c.png
setOffscreenPageLimit原始碼
14093317-8302f1755f1876a0.png

二.實現Fragment懶載入

介紹一種懶載入程式碼BaseLazyFragment:

1.首先是setUserVisibleHint()方法的重寫

14093317-2d7137f51c6d9e6c.png
setUserVisibleHint()

第一個判斷語句主要是兩個判斷條件

(1)當isVisibleToUser 為true則進行資料載入,當isVisibleToUser為false則不進行資料載入

(2)判斷isInit值,對於已經載入過資料的fragment,再次被滑動到也不在進行載入資料,也就是每個fragment僅做一次資料載入工作第二個判斷語句是針對以初始化的fragment,再根據是否可見來判斷顯示、執行生命週期。

2.然後回到onCreateView()上。在onCreateView()裡,對要懶載入的fragment新增FragmeLayout.

14093317-36c21d5827587953.png
onCreateView()

3.然後是對fragment生命週期的處理,每個狀態下以Fragment的回撥方法名字後面要加個Lazy的方法命名,並依次呼叫。

14093317-d2acab6a87261e1f.png
生命週期函式

4.載入view,我們在onCreateView()裡,對要懶載入的fragmentli,新增FrameLayout,設定setContentView()是為了當我們將fragment移至可見,則能夠根據判斷,替換掉原來的FrameLayout佈局。因為,移至可見時,該fragment會再次呼叫onCreateView()方法

14093317-bde1d27bfcd2af79.png
setContentView()

思路:

* 懶載入Fragment</h1> 只有建立並顯示的時候才會呼叫onCreateViewLazy方法

* 懶載入的原理onCreateView的時候Fragment有可能沒有顯示出來。

* 但是呼叫到setUserVisibleHint(boolean isVisibleToUser),isVisibleToUser =

* true的時候就說明有顯示出來

* 但是要考慮onCreateView和setUserVisibleHint的先後問題所以才有了下面的程式碼

* 注意:

* 《1》原先的Fragment的回撥方法名字後面要加個Lazy,比如Fragment的onCreateView方法, 就寫成onCreateViewLazy

* 《2》使用該LazyFragment會導致多一層佈局深度

 fragment一共四種情況:

        可見、初始化;

        可見、未初始化;

        不可見、初始化;

        不可見、未初始化;

        邏輯分析,假設setOffscreenPageLimit(1),共預載入2個fragment:

        剛進來,1是可見,且要初始化的,2是不可見、未初始化,第三個3是不繫結到activity的。

        於是,1走途徑1,2走途徑2.

       然後,假設滑動了,1滑到2。此時,1不可見,且已初始化了,2是可見,將要初始化,3繫結到activity上,為不可見、未初始化。

          於是,1由於預載入的原因,未解除與檢視的聯絡。所以onPause()、onStop()、onDestoryView()未執行,

          並且,由於1不可見,setUserVisibleHint()執行了。所以, isStart設定為false,即不可見;並呼叫onFragmentStopLazy();

          2可見,同理由於預載入原因,處於可見狀態時,不會再呼叫onCreateView(),而是會呼叫setUserVisibleHint(),

        所以,isStart設定為true;onFragmentStartLazy();

         3呢,呼叫onCreateView(),又由於3不可見且未初始化,則不執行。所以,載入的是個FrameLayout

相關文章