1. 程式人生 > >Android多個fragment懶載入的坑(卡頓)

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的預載入,就目前來說,我用的這個方法還是挺靠譜的。