fragment+viewpager懒加载的两种方式(setMaxLifecycle方式 和 setUserVisibleHint方式)

314次阅读
没有评论

先说一下,setUserVisibleHint方式官方已经不推荐使用了,取而代之的是setMaxLifecycle

效果如下图: fragment+viewpager懒加载的两种方式(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();
        }
    }

迷鹿, lostfawn
版权声明:本站原创文章,由迷鹿, lostfawn2021-05-28发表,共计4518字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
载入中...
召唤伊斯特瓦尔