20515
写上一篇ViewPager2软文时,我发现最新的
Fragment
代码淘汰了
setUserVisibleHint
方法,转而支持用
setMaxLifecycle
方法,
setMaxLifecycle
言外之意是
设置最大生命周期
,懂行的人应该知道,
Fragment
一直都是无法直接设置生命周期,必须通过
add
、
attach
、
remove
、
detach
、
show
、
hide
方法间接干预,本来就此功能,简单介绍一下
setMaxLifecycle
的原理和上手效果;
阅读指南:
本文基于
androidx 1.1.0-alpha07
版本的
fragment
进行,也是支持
setMaxLifecycle
的最低版本
本文会根据
FragmentPagerAdapter
进行
setMaxLifecycle
示例应用讲解
setMaxLifecycle
定义在
FragmentTransaction
中,和之前的
add
、
attach
、
remove
、
detach
、
show
、
hide
等方法是并列关系;
FragmentTransaction
public FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment,
@NonNull Lifecycle.State state) {
addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state));
return this;
复制代码
参数解读:
fragment
即需要操作的Fragment对象,前提条件是这个
fragment
必须已经加到
FragmentManager
中;
state
Lifecycle.State
枚举类型,该参数的使用条件是至少是
Lifecycle.State.CREATED
,否则报
IllegalArgumentException
异常
Lifecycle.State
一共有五个状态,最低要求是
Lifecycle.State.CREATED
,所以该方法可用的参数有
CREATED
、
STARTED
、
RESUMED
,
State
和
生命周期方法
有何区别,下面简单解释一下:
生命周期状态理解
在Fragment中,定义了五种
State
,这里的
State
并非上面说
Lifecycle.State
,但是逻辑基本上是一致的;
INITIALIZING
初始状态
CREATED
已创建状态
ACTIVITY_CREATED
完全创建,但是没有started
STARTED
创建并启动,可见不可操作
RESUMED
创建启动并可操作
本文内容只对
CREATED
、
STARTED
、
RESUMED
这三个状态讲解,由于Fragment中定义的
mState
和
Lifecycle.State
不是同一状态,在本文视为同一概念;
与生命周期对应关系
各位肯定都知道Fragment生命周期有
onDestory
,
onStop
等方法,但是状态却没有这么多,那么如何标识状态和对应关系,下面给出对应关系;
首先,我把生命周期方法从
onCreate
->
onCretateView
->
onStart
->
onResume
->
onPause
->
onStop
->
onDestoryView
->
onDestory
视为从小到大排序;
同样的,我们把生命周期状态
CREATED
->
STARTED
->
RESUMED
视为从小到大排序;
CREATED状态
CREATED
即已创建状态,狭义的理解是生命周期方法走到
onCreate
,如果当前fragment状态已大于
CREATED
,则会使fragment生命周期方法走到
onDestoryView
,如果小于
CREATED
,则走到
onCreate
;所以
CREATED
有两种情况;
STARTED状态
同理,
STARTED
状态也有两种情况,如果当前fragment状态已大于
STARTED
,则会使fragment生命周期方法走到
onPause
,如果小于
CREATED
,则走到
onStart
;
RESUMED状态
RESUMED
表示的状态比较特殊,只代表
onResume
状态,无论大到小还是小到大,最终都是停留到
onResume
状态;
以上生命周期状态扭转结论基于
FragmentManagerImpl.moveToState()
方法提取,如有误导,请指教
setMaxLifecycle
可以单独使用,也可以配合
add
等方法组合使用,首先,我们分析单独执行
add
命令的状态变化:
单独执行add操作
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.frame_layout,cardFragment)
fragmentTransaction.commit()
add配合setMaxLifecycle(Lifecycle.State.CREATED)
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.frame_layout,cardFragment)
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.CREATED)
fragmentTransaction.commit()
add配合setMaxLifecycle(Lifecycle.State.STARTED)
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.frame_layout,cardFragment)
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.STARTED)
fragmentTransaction.commit()
add配合setMaxLifecycle(Lifecycle.State.RESUMED)
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.frame_layout,cardFragment)
fragmentTransaction.setMaxLifecycle(cardFragment, Lifecycle.State.RESUMED)
fragmentTransaction.commit()
单独使用setMaxLifecycle
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction()
fragmentTransaction.setMaxLifecycle(cardFragment, xxx)
fragmentTransaction.commit()
对RESUMED
状态的Fragment进行操作CREATED
操作
对RESUMED
状态的Fragment进行操作STARTED
操作
对RESUMED
状态的Fragment进行操作CREATED
操作,在进行STARTED
操作
由于篇幅原因,就不一一介绍各种组合情况,只要弄清楚生命周期状态,不论是状态是升还是降,不论组合还是单用,你都可以驾驭;
FragmentPagerAdapter变动
由于setMaxLifecycle
带来了生命周期设置,替换掉了老旧的setUserVisibleHint
方法,所以在FragmentPagerAdapter
中也进行了适配
FragmentPagerAdapter
public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;
public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;
private final int mBehavior;
public FragmentPagerAdapter(@NonNull FragmentManager fm) {
this(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);
public FragmentPagerAdapter(@NonNull FragmentManager fm,@Behavior int behavior) {
mFragmentManager = fm;
mBehavior = behavior;
复制代码
最新的FragmentPagerAdapter
用一个mBehavior
来控制setUserVisibleHint
和setMaxLifecycle
二选一的局面;
mBehavior
在构造方法中指定;
从代码可以看出,用setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.State.STARTED)
替代setUserVisibleHint(false)
,用setMaxLifecycle(fragment, Lifecycle.State.RESUMED)
替代setUserVisibleHint(true)
;
为什么要用Lifecycle.State.STARTED
?因为这里本质上用的是add
+Lifecycle.State.STARTED
和attach
+Lifecycle.State.STARTED
组合;
最终的结果是不可见的Fragment只会走到生命周期onStart
方法,不会走onResume
方法;
懒加载新方案
综上,过去使用setUserVisibleHint
来控制Fragment懒加载,在最新版的FragmentPagerAdapter里有新思路,可以切换到BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
模式,在FragmentonResume
里判断,更符合显示逻辑;
切换到BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
模式,需要调用俩参数的构造方法:
new FragmentPagerAdapter(getSupportFragmentManager(),FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
复制代码
总结
破事水了小半天,本文到底说了什么内容,还是做个总结吧:
首先使用setMaxLifecycle
能进一步的控制Fragment
生命周期,一句话形容就是对add
、attach
等命令的补充;
其次该功能在官方控件中得以运用,改善了ViewPager
+Fragment
的使用体验,懒加载注意点;
最后鼓励大家(主要是自己)多看源码,夯实基础,方能不变应万变,本文结束。