fragment+viewpager實現懶加載的兩種方式(setMaxLifecycle方式 和 setUserVisibleHint方式)

先說一下,setUserVisibleHint方式已經不推薦使用了,替代它的方案就是setMaxLifecycle,這裏不再具體講解setMaxLifecycle(講我也不會哈哈)

推薦一篇文章:setMaxLifecycle講解,想具體瞭解可以看看。

效果:

在這裏插入圖片描述

setMaxLifecycle方式實現fragment懶加載:(需要使用androidx)

第一步:

爲FragmentPagerAdapter的構造函數 添加參數FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

FragmentPagerAdapter適配器構造方法中有一個behavior參數(下面代碼的第二個參數),
把這個參數的值設置爲:FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

這樣就使用setMaxLifecycle來限制了fragment的生命週期,fragment的onReseume()只有當fragment顯示在屏幕上時纔會執行,這樣就可以把加載數據的方法放在onResume()方法中來實現懶加載了

這樣就完成了第一步(下面有完整代碼)

FragmentPagerAdapter(FragmentManager fm, int behavior, List<BaseFragment> fragmentList) // 看第二個參數

第一步完整代碼:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager viewPager = findViewById(R.id.viewpager);
        List<BaseFragment> fragmentList = new ArrayList<>();
        fragmentList.add(new Fragment1());
        fragmentList.add(new Fragment2());
        fragmentList.add(new Fragment3());
        // 爲MyPagerAdapter適配器設置FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 參數
        MyPagerAdapter myPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(),
                FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, fragmentList);
        viewPager.setAdapter(myPagerAdapter);
        // 設置預加載爲3頁,來測試懶加載是否成功
        viewPager.setOffscreenPageLimit(3); 
    }

    // 適配器
    public class MyPagerAdapter extends FragmentPagerAdapter { 
        List<BaseFragment> fragmentList;

        MyPagerAdapter(@NonNull FragmentManager fm, int behavior, List<BaseFragment> fragmentList) {
            super(fm, behavior);
            this.fragmentList = fragmentList;
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }
    }
}
第二步:

封裝一個BaseFragment:通過它的onReseume()方法來控制具體每個fragment的數據懶加載

第二步完整代碼:

public abstract class BaseFragment extends Fragment {
    private boolean isOk = false; // 是否完成View初始化
    private boolean isFirst = true; // 是否爲第一次加載
    public View view;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = getMyView(inflater, container, savedInstanceState); // 獲取子fragment的view
        initView();
        isOk = true; // 完成initView後改變view的初始化狀態爲完成
        return view;
    }
    // 子fragment初始化view的方法
    abstract void initView();
    // 獲取子fragment的view
    abstract View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);

    @Override
    public void onResume() {
        super.onResume();
        initLoadData(); // 在onResume中進行數據懶加載
    }

    private void initLoadData() {
        if (isOk && isFirst) { // 加載數據時判斷是否完成view的初始化,以及是不是第一次加載此數據
            loadData();
            isFirst = false; // 加載第一次數據後改變狀態,後續不再重複加載
        }
    }
    // 子fragment實現懶加載的方法
    abstract void loadData();

}

第三步:

具體fragment如何運用

第三步具體代碼:

public class Fragment1 extends BaseFragment { // 繼承第二步中的BaseFragment,實現對應方法

    @Override
    void initView() { //此處進行view初始化
        TextView textView = view.findViewById(R.id.text_fragment1);
    }

    @Override //此處把當前fragment的視圖進行初始化
    View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment1, container, false);
    }

    @Override
    void loadData() { //此處是實現了懶加載的加載數據的方法
        Toast.makeText(getContext(), "123", Toast.LENGTH_SHORT).show();
    }
}

setUserVisibleHint方式實現懶加載:(只是更改了第二步與第一步中的一些方法)

第二步改爲:

public abstract class BaseLazyFragment extends BaseFragment {
    private boolean isFirst = true; // 是否爲第一次加載
    private boolean isView = false; //view是否加載完(防止空指針)
    private boolean isisVisible = false; //是否對用戶可見
    public View view;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        view = getMyView(inflater, container, savedInstanceState); // 獲取子fragment的view
        initView();
        isView = true;
        myLoadData(); //加載數據
        return view;
    }

    // 子fragment初始化view的方法
    public abstract void initView();

    // 獲取子fragment的view
    public abstract View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            isisVisible = true;
            myLoadData();
        } else {
            isisVisible = false;
        }
    }
 private void myLoadData() {
        if (isFirst && isisVisible && isView) { // 加載數據時判斷是否完成view的初始化,以及是不是第一次加載此數據,以及用戶是否切換到了這個fragment
            loadData();
            isFirst = false; // 加載第一次數據後改變狀態,後續不再重複加載
        }
    }
    // 子fragment實現懶加載的方法
    public abstract void loadData();
}

第一步中MyPagerAdapter的構造方法改爲下面的:

// 適配器
    public class MyPagerAdapter extends FragmentPagerAdapter { 
        List<BaseFragment> fragmentList;

        MyPagerAdapter(@NonNull FragmentManager fm,List<BaseFragment> fragmentList) {
            super(fm);
            this.fragmentList = fragmentList;
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章