Android多個fragment懶載入的坑(卡頓)
在Android開發中,有很多種情況都是viewpage+fragment左右滑動進行佈局的,例如下面的今日頭條
在今日頭條app上,我們可以看到,其頂部都是一欄的型別資料來源,可滑動,可聯動下面的viewpage裡的fragment,但是很多時候,viewpage+fragment中的fragment每次都將走onCreate方法,導致在視覺上造車一定的卡頓,而且在載入當前fragment的時候,往往會預載入下一個fragment的資料,造成視覺上的誤解。
思路:
在嘗試過很多方法之後,終於找到了一個比較好的解決方法。使用Fragment自帶的setUserVisibleHint()來判斷當前fragment是否對使用者可見,根據回撥的isVisibleToUser引數來進行相關的邏輯判斷。建立一個變數isVisible來拿到fragment是否可見的標誌。
但是直接根據isVisible判斷就載入資料,很有可能很多控制元件在OnCreateView()方法還未執行完成的情況下出現NullPointerException空指標的情況。所以我們需要在控制元件初始化完成並且使用者可見的時候,再去進行資料的載入。
最後整合一個通用的LazyloadFragment實現懶載入的fragment
public abstract class LazyloadFragment extends Fragment {
protected View rootView;
private boolean isInitView = false ;
private boolean isVisible = false;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(setContentView(), container, false);
init();
isInitView = true;
isCanLoadData ();
return rootView;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//isVisibleToUser這個boolean值表示:該Fragment的UI 使用者是否可見,獲取該標誌記錄下來
if(isVisibleToUser){
isVisible = true;
isCanLoadData();
}else{
isVisible = false;
}
}
private void isCanLoadData(){
//所以條件是view初始化完成並且對使用者可見
if(isInitView && isVisible ){
lazyLoad();
//防止重複載入資料
isInitView = false;
isVisible = false;
}
}
/**
* 載入頁面佈局檔案
* @return
*/
protected abstract int setContentView();
/**
* 讓佈局中的view與fragment中的變數建立起對映
*/
protected abstract void init();
/**
* 載入要顯示的資料
*/
protected abstract void lazyLoad();
}
這裡需要使用FragmentPagerAdapter
,才可以顯示的呼叫setUserVisibleHint()
這個方法
子fragment的載入資料的寫法:
public class PageFragment extends LazyloadFragment implements XRecyclerView.LoadingListener {
private CommonAdapter<String> adapter;
private ArrayList<String> datas = new ArrayList<>();
private XRecyclerView recyclerView;
private Handler handler = new Handler();
@Override
public int setContentView() {
return R.layout.fragment_page;
}
@Override
public void init() {
recyclerView = rootView.findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new CommonAdapter<String>(getActivity(),R.layout.item,datas) {
@Override
protected void convert(ViewHolder holder, String s, int position) {
}
};
recyclerView.setAdapter(adapter);
recyclerView.setPullRefreshEnabled(true);
recyclerView.setLoadingListener(this);
}
@Override
public void lazyLoad() {
recyclerView.refresh();
}
@Override
public void onRefresh() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
recyclerView.refreshComplete();
for(int i=0;i<10;i++){
datas.add("");
}
adapter.notifyDataSetChanged();
}
},500);
}
@Override
public void onLoadMore() {
}
}
fragment的呼叫還是像以前一樣的呼叫。
總結:
fragment+viewpage這種模式確實很消耗手機效能與記憶體,特別是在一些即將淘汰的手機上出現的卡頓也將特別嚴重,這樣實現的懶載入模式可以控制只加載一個fragment
,並且還是載入當前的fragment
,而不會觸發下一個fragment
的預載入,就目前來說,我用的這個方法還是挺靠譜的。