最近項目中用到ViewPager+Fragment的形式構(gòu)造UI,由于ViewPager的實現(xiàn)機制會先為后面未顯示的Fragment提前加載數(shù)據(jù),這樣會造成沒必要的重復(fù)請求,浪費用戶瀏覽量。所以就需要用到懶加載卡乾。
而所謂的懶加載是指在Fragment的UI對用戶可見時再加載數(shù)據(jù)桂敛,那怎么實現(xiàn)懶加載呢?通常的想法是查看Fragment的方法有沒有當(dāng)用戶可見時調(diào)用的慕匠,通過翻閱官方文檔找到一個方法可以解決我們的問題。public void setUserVisibleHint(boolean isVisibleToUser) 下面是官方對這個方法的注解:
Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
我們可以通過isVisibleToUser參數(shù)的值來判斷是否已經(jīng)對用戶可見了域醇,true表示對用戶可見台谊,false表示對用戶不可見。那么setUserVisibleHint是在什么時候調(diào)用呢譬挚,下面是我寫了個ViewPager+Fragment的demo所打印的日志
通過兩個fragment的日志對比我們會發(fā)現(xiàn)setUserVisibleHint方法的調(diào)用時機并不確定锅铅,在第一個Fragment中是在onCreateView之前調(diào)用,而在第二個Fragment中是在onCreateView之后調(diào)用减宣,這里之所以提到onCreateView是因為Fragment的視圖是在onCreateView方法中創(chuàng)建的盐须。如果直接在setUserVisibleHint的參數(shù)為true時加載數(shù)據(jù),就會有一種可能蚪腋,網(wǎng)絡(luò)數(shù)據(jù)加載完后Fragment的視圖還沒創(chuàng)建丰歌,這時候我們無法把數(shù)據(jù)放置到view當(dāng)中,如果代碼寫的不嚴謹?shù)脑挸绦驎苯颖罎ⅰ?/p>
這時候我們就需要維護一個參數(shù)mViewCreated用來標識視圖是否已經(jīng)創(chuàng)建屉凯,只有當(dāng)用戶可見并且視圖已經(jīng)創(chuàng)建時才加載數(shù)據(jù)立帖。這時候可以封裝如下代碼:
現(xiàn)在讓我們回到fragment1日志圖,會發(fā)現(xiàn)第一個Fragment的setUserVisibleHint調(diào)用時機都是在onCreateView之前悠砚,所以這樣封裝會造成一個問題晓勇,第一個Fragment的數(shù)據(jù)沒有加載。那該如何處理呢灌旧?我們做以下修改绑咱,在onActivityCreated同樣加載一遍數(shù)據(jù)。這樣可以保證第一個Fragment和后面的Fragment都加載到數(shù)據(jù)枢泰,而由于setUserVisibleHint為true的調(diào)用時機后面的Fragment不會重復(fù)加載數(shù)據(jù)描融。我們做如下修改:
基本上寫到這里就已經(jīng)結(jié)束了,但通過使用我們發(fā)現(xiàn)一個問題衡蚂,F(xiàn)ragment每次可見時都會加載一邊數(shù)據(jù)窿克,我們省流量的初衷并沒有實現(xiàn)骏庸,下面我們做了如下修改:通過維護參數(shù)mLoadFinished來判斷是否已經(jīng)加載過數(shù)據(jù),完整代碼如下
之所以暴露出去個setLoadDataSuccess是為了防止數(shù)據(jù)沒有加載成功年叮。