先说一下,setUserVisibleHint方式官方已经不推荐使用了,取而代之的是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(); } }