背景
-
項目中不可避免會用到,這裏記錄一下,方便自己和同學們,好記性不如爛筆頭。
-
理解後就不用專門記了,因爲也確實沒有太多複雜的東西。
-
因爲 viewPager 的預加載機制,所以我們爲了讓 fragment 使用起來更加流暢,提升性能,所以需要對 fragment 做一個懶加載的操作,當 fragment 對用戶不可見時不加載數據。
分析實現
- 最開始的 fragment 代碼如下:
package com.example.myapplication.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.myapplication.R;
/**
* 懶加載寫法
*/
public class MyFragment extends Fragment {
public MyFragment() {
// Required empty public constructor
}
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if (view == null && savedInstanceState == null){
view = inflater.inflate(R.layout.fragment_my, container, false);
}
return view;
}
}
這個沒有疑問。
- 只有當 fragment 對用戶可見且 fragment 的視圖已經加載完成以後,我們纔可以做對應的數據加載操作,所以這裏引入兩個布爾變量分別標識,如下圖示:
初始化均賦值爲 false。
- 因爲是跟 viewPager 相結合,所以在 fragment 中判斷對用戶是否可見我們重寫
setUserVisibleHint
生命週期方法進行判斷,如下圖示:
- 在 onCreateView 方法中對view已經加載完成標識置爲 true,如下圖示:
- 所以此時當對用戶可見且 view 已經加載完成後,我們在 onResume 方法中做懶加載操作,如下圖示:
- 此時做完懶加載操作後,記得恢復先前的標識,防止數據重複加載。如下圖示:
-
因爲預加載機制,有的 fragment 已經初始化完成了,也執行到了 onResume 生命週期方法,但是這時候對用戶不可見,所以在 onResume 方法裏的 lazyLoad 方法並不會執行,那麼這種情況下也就不會執行懶加載操作。
-
不過這個時候,當滑動fragment 對用戶可見時,會回調
setUserVisibleHint
生命週期方法,所以我們可以在這裏面進行懶加載操作,也就解決了上面說的情況。如下圖示:
-
最後,可能有的同學會說,你第一次創建fragment的時候,在 setUserVisibleHint 中調用了 lazyLoad 方法,也在 onResume 中調用了 LazyLoad 方法,你這不是就重複加載數據了嗎?
-
說明如下:因爲 setUserVisibleHint 方法會優先於 onCreateView 方法執行(如下圖示),所以此時 view 還未加載完,那麼上面所說的 isViewCreated 標識值爲 false ,所以此時 lazyLoad 方法其實並不會執行。因爲只有同時滿足對用戶可見且 view 已經加載完成纔去加載數據。
所以問題得以解決。
完整代碼
package com.example.myapplication.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.myapplication.R;
/**
* 懶加載寫法
*/
public class MyFragment extends Fragment {
private boolean isVisible = false;// 對用戶是否可見標識
private boolean isViewCreated = false;// view是否已經加載完成標識
public MyFragment() {
// Required empty public constructor
}
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if (view == null && savedInstanceState == null){
view = inflater.inflate(R.layout.fragment_my, container, false);
}
isViewCreated = true;// view 已經加載
return view;
}
@Override
public void onResume() {
super.onResume();
lazyLoad();
}
/**
* 延遲加載 - 對用戶可見且view已經加載完成
*/
private void lazyLoad() {
if(isVisible && isViewCreated){
loadData();
reset();// 恢復標識,防止重複加載
}
}
/**
* 恢復標記 防止重複加載
*/
private void reset(){
isViewCreated = false;
isVisible = false;
}
/**
* 加載數據操作
*/
private void loadData() {
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser){
isVisible = true;// 對用戶可見
lazyLoad();
}else {
isVisible = false;// 對用戶不可見
}
}
}
上面就是完整的一個懶加載實現的代碼,希望對同學們加深理解有幫助。
技術永不眠,我們下期見!