先说一下,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();
}
}