在很多應用中,首頁都是由三個或四個Fragment構(gòu)成,且都是上中下結(jié)構(gòu)。這種設計方式大行其道,但是作為首頁,每一個Fragment的內(nèi)容肯定是較多的,這個時候直接加載出來,或是默認加載兩三個都是有點耗費資源的,特別是在打開應用的時候,如果操作過多可能會卡,所以很多應用在首頁都會使用Fragment懶加載,例如微信。
對于如何懶加載,也算是Android中比較簡單的內(nèi)容,本文只是針對這個問題提供一種比較通用的解決方法。如果你對Android開發(fā)比較熟悉的話,不要讓本文浪費你的時間。如果你閱讀本文,你將會學習如下內(nèi)容:
- Fragment 中 setUserVisibleHint 函數(shù)
- 上中下結(jié)構(gòu)的首頁設計實現(xiàn)
- Fragment 懶加載的一種實現(xiàn)方式
本文中代碼可在此處查看:https://github.com/Lee-swifter/LazyFragmentDemo
一,創(chuàng)建懶加載基類Fragment
這個函數(shù)簡單來說就是用來表明該Fragment是否向用戶展示,如果用戶能夠看到該Fragment,那么這個函數(shù)的參數(shù)則為true。說起來簡單,但是這個函數(shù)有個特別需要注意的地方就是此函數(shù)不是生命周期函數(shù)。也就是說,該方法有可能在脫離生命周期的地方調(diào)用,例如當Fragment還沒有onCreateView時,這個函數(shù)就有可能調(diào)用,而此時如果控制界面的話,就會出現(xiàn)NullPointerException。在進行懶加載的處理時,這一點需要特別照顧。
在這種懶加載方式中,先創(chuàng)建一個LazyFragment實現(xiàn)懶加載的所有操作,然后再創(chuàng)建其子類作為實際使用。這樣的話,只要是繼承自這個LazyFragment的Fragment就會具有懶加載的功能,方便實際使用。
1. 首先,為了進行懶加載,設定幾個標志:
private boolean hasLoaded = false; //標識是否已經(jīng)加載過
private boolean hasCreated = false; //標識onCreateView是否已調(diào)用
private boolean needInit = false; //標識是否需要在onCreateView中
2. 在setUserVisibleHint中進行判斷處理
if (isVisibleToUser && !hasLoaded) { //如果當前Fragment向用戶展示且沒有加載過,進行下一步判斷
if (hasCreated) { //如果onCreateView已經(jīng)被創(chuàng)建,此時進行加載
initWrapper();
} else { //如果Fragment沒有創(chuàng)建,那么設置標記,在onCreateView中加載
needInit = true;
}
}
此處進行的一些判斷操作就是為了處理此函數(shù)在Fragment還沒有創(chuàng)建界面時的情況。如果出現(xiàn)了這種情況,那么設置標記位在onCreateView中加載。其中initWrapper函數(shù)來進行加載界面,而此時加載的僅僅為該LazyFragment的界面,只包含一個ProgressBar和FramentLayout。其中ProgressBar僅僅為加載之前的展示,而FramentLayout則是用來放置其子類布局的。
private void initWrapper() {
LayoutInflater.from(getContext()).inflate(setContentView(), content);
initialize();
fadeOutView(progressBar, mShortAnimationDuration);
fadeInView(content, mShortAnimationDuration);
hasLoaded = true;
}
3. 創(chuàng)建子類使用的函數(shù)
/**
* 供子類使用,子類fragment初始化操作,此函數(shù)內(nèi)部真正開始進行頁面的一些列操作
*/
abstract void initialize();
/**
* 子類fragment設置布局,返回fragment要設定的布局
* @return 子類fragment要顯示的布局
*/
@LayoutRes
abstract int setContentView();
上面基本都是創(chuàng)建Fragment懶加載基類重點的地方,其子類只需要復寫上面兩個函數(shù)就可以以懶加載的方式使用。其他內(nèi)容可以使用查看項目倉庫。
二,創(chuàng)建懶加載子類Fragment
其實只要實現(xiàn)了基類,那么懶加載框架就已經(jīng)基本完成,繼承子類只是來使用,這個地方是比創(chuàng)建其基類要容易很多。創(chuàng)建其子類只需要復寫這兩個函數(shù),這樣就可以作為一個普通的Fragment來使用:
@Override
void initialize() {
//用來進行本Fragment的初始化操作
}
@Override
int setContentView() {
return R.layout.fragment; //返回本類所的布局
}
三,創(chuàng)建使用懶加載Fragments的Activity
一般來說使用標簽頁的Activity,都是上中下結(jié)構(gòu),上面Toolbar,中間FrameLayou用來顯示內(nèi)容,下面就是 Bottom Navigation Tab。這種實現(xiàn)并沒有什么難度,也有很多種實現(xiàn)方式,特別是底部導航欄。而在中間,本例子種使用的是ViewPager,這樣可以實現(xiàn)左右滑動切換,也是微信的加載方式。其中代碼與Fragment懶加載無關(guān),所以就不再贅述。
在具體代碼倉庫中,實現(xiàn)了這種懶加載的這種方式,如有需要的可以去看看:https://github.com/Lee-swifter/LazyFragmentDemo