前言
- 为什么要对Fragment使用懒加载?
在项目中,使用Fragment的时候,往往是和ViewPager一起使用,而ViewPager有默认的加载机制,会预加载当前页的前后两个页面(执行onResume方法),如果几个页面都有数据操作的逻辑,比如加载网络数据,即使是不可见的页面也会加载数据,竞争网络流量,这样会造成一定的资源浪费,所以会用到懒加载。
- 什么是懒加载?
在很多地方都用到这个概念,比如懒加载单例模式,就是在使用时才会加载,如果一直不使用就一直不加载。
由于Fragment提供的setUserVisibleHint(boolean isVisibleToUser)已经标记位@Deprecated,转而使用setMaxLifecycle方法,今天讲一下使用setMaxLifecycle方法实现Fragment的懒加载。
介绍
FragmentTransaction
setMaxLifecycle方法位于FragmentTransaction类中,内容如下:
@NonNull
public FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment,
@NonNull Lifecycle.State state) {
addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state));
return this;
}
其中包含两个参数:
- fragment:需要操作的Fragment实例
- state:状态,Lifecycle.State枚举类型,包含5个状态
Lifecycle.State的状态:
- INITIALIZED:初始化完成状态,Fragment已经构建完成,未调用到onCreate;
- CREATED:创建完成状态,在onCreate方法之后,onStop之前;
- STARTED:在onStart方法之后,onPause之前;
- RESUMED:在onResume方法之后;
- DESTROYED:在onDestroyed方法之后。
setMaxLifecycle可直接解释为:设置Fragment所处的最大声明周期。如果Fragment超过了当前设置的最大周期值,会将Fragment降到设置的值。
各个状态对应可执行到的生命周期如下:
- INITIALIZED:无法设置此方法,Cannot set maximum Lifecycle below CREATED;
- CREATED:onAttach -> onCreate;
- STARTED:onAttach -> onCreate -> onCreateView ;
- RESUMED:onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume;
- DESTROYED:无法设置此方法,Cannot set maximum Lifecycle below CREATED。
其实对我们可以说使用的只有中间3种,看一下如何使用。
使用
1.初始化
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.layout_fragment, mFragment);
fragmentTransaction.setMaxLifecycle(mKingFragment, Lifecycle.State.CREATED);
fragmentTransaction.commit();
通过这个方法,让Fragment添加时的生命周期执行到onCreate。
很明显可以看出,如果使用懒加载时,可以将非前端显示的Fragment设置到如下状态,将加载数据的方法写到onCreate之后的生命周期内,如需加载数据,再通过下面的方法将最大值往后跳转。
2.更新
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setMaxLifecycle(mFragment, Lifecycle.State.RESUMED);
fragmentTransaction.commit();
通过这个方法,可以让Fragment执行 onCreateView -> onActivityCreated -> onStart -> onResume。
更新方法只能自上而下的改变状态:CREATED -> STARTED -> RESUMED,否则不会响应,而生命周期回调也会随着状态的更新而顺序调用下去。
FragmentPagerAdapter
在ViewPager+Fragment的场景中,FragmentPagerAdapter也做了响应的适配。
源码中默认的构造方法已经弃用,转而使用需要提供Behaviour参数的构造方法
@Deprecated
public FragmentPagerAdapter(@NonNull FragmentManager fm) {
this(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);
}
public FragmentPagerAdapter(@NonNull FragmentManager fm,
@Behavior int behavior) {
mFragmentManager = fm;
mBehavior = behavior;
}
Behavior只有一个值可以提供了,因为另一个值也弃用了。也就是说FragmentPagerAdapter默认提供了懒加载,注释中已经解释。
@Deprecated
public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;
/**
* Indicates that only the current fragment will be in the Lifecycle.State.RESUMED state. All other Fragments are capped at Lifecycle.State.STARTED.
*/
public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;
所以ViewPager+Fragment简单实现如下:
//初始化新建的Fragment,添加入list中
List<Fragment> fragmentList = new ArrayList<>(2);
fragmentList.add(new Fragment1());
fragmentList.add(new Fragment2());
//获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
//初始化FragmentAdapter,提供参数FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
MyFragmentAdapter adapter = new MyFragmentAdapter(fragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, fragmentList);
//在layout中的viewpager
ViewPager viewPager = findViewById(R.id.vp_root);
viewPager.setAdapter(adapter);
总结:
本节内容很简单,通过setMaxLifecycle可以设置Fragment的生命周期最大值,如果需要懒加载,可以先将最大值设置为靠前,而在后面调用的生命周期回调中实现加载数据的方法。
ViewPager+Fragment默认提供了懒加载,使用FragmentPagerAdapter即可。