Android setMaxLifecycle和BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT浅析

前言

最近公司动荡,我在的项目受大环境影响收益每年下滑,可能要领盒饭了,所以最近都在复习相关基础内容,毕竟小脑袋瓜会忘记以前学过的东西。
在ViewPager和Fragment的懒加载中,具体的原理是怎么样的呢?为什么能只执行显示的Fragment的onResume方法?

疑问

借用一篇文章的说明

1.Lifecycle.State.STARTED对应Fragment的STARTED状态,如果当前Fragment状态低于STARTED,那么Fragment的状态会变为STARTED,以当前Fragment状态为CREATED为例,接下来会依次执行onCreateView()、onActivityCreate()和onStart()方法;
2.如果当前Fragment状态高于STARTED,也就是RESUMED,那么Fragment的状态会被强制降为STARTED,接下来会执行onPause()方法。

疑问一:设置STARTED后是否执行onResume?那是否能交互?
疑问二:FragmentPagerAdapter如果设置STARTED的话,就不会执行到onResume方法,懒加载就无法实现,更没有降级一说?

探索

疑问一:

实践是检验最好的结果,
设置CREATE的:只走了onCreate方法,onStart和onResume不触发,fragment也不显示
设置STARTED的话:不执行onResume,但也不影响页面可交互。

前备知识在疑问二有记录

疑问二

原有的懒加载是用 setUserVisibleHint实现,但查看源码已经给设置成@Deprecated
在这里插入图片描述
注释的setMaxLifecycle是什么呢?单看意思就是最大生命周期,就是一个生命周期阻断的作用。
在这里插入图片描述
用法如下

  FragmentTransaction mCurTransaction = getSupportFragmentManager().beginTransaction();
  mCurTransaction.setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.State.STARTED);

其中的入参中LifeCycle.State是个枚举类型,

public enum State {
    DESTROYED,
    INITIALIZED,
    CREATED,

    /**
     * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
     * is reached in two cases:
     * <ul>
     *     <li>after {@link android.app.Activity#onStart() onStart} call;
     *     <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
     * </ul>
     */
    START,

    /**
     * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
     * is reached after {@link android.app.Activity#onResume() onResume} is called.
     */
    RESUMED;
}

看注释大概意思是:
START:创建生命周期只会执行到onStart(onResume不执行),之后的都统一是onPause(onStop不执行)。

fragment创建:onAttach->onCreate->onCreateView->onActivityCreate->onStart->onResume
fragment结束:onPause->onStop->onDestoryView->onDestory->onDetach

知道这些我们再看看FragmentPagerAdapter的源码

首先时构造函数
在这里插入图片描述
mBehavior设置为BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT才会懒加载

而用到BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT判断只有两个地方:

1.创建Fragment

   @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
      ***省略
    if (fragment != mCurrentPrimaryItem) {
        fragment.setMenuVisibility(false);
        if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {//注意不执行setUserVisibleHint
            mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
        } else {
            fragment.setUserVisibleHint(false);
        }
    }

    return fragment;
}

其实就是BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT的时候设置setMaxLifecycle为Lifecycle.State.STARTED,也就是说ViewPager的所有fragment的生命周期只会走到onStart,那onResumet是何时调用?

2.设置当前fragment

    @Override
    public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        Fragment fragment = (Fragment)object;//即将显示的fragment
        if (fragment != mCurrentPrimaryItem) {//mCurrentPrimaryItem为即将隐藏的fragment
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {//开启懒加载
                    if (mCurTransaction == null) {
                        mCurTransaction = mFragmentManager.beginTransaction();
                    }
                    mCurTransaction.setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.State.STARTED);//设置即将隐藏的fragment为Start状态
                } else {
                    mCurrentPrimaryItem.setUserVisibleHint(false);
                }
            }
            fragment.setMenuVisibility(true);
            if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {//懒加载
                if (mCurTransaction == null) {
                    mCurTransaction = mFragmentManager.beginTransaction();
                }
                //主要标注1
                mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED);//设置即将显示的fragemnt为Resume状态
            } else {
                fragment.setUserVisibleHint(true);
            }

            mCurrentPrimaryItem = fragment;//mCurrentPrimaryItem 只有这里赋值 默认为空
        }
    }

代码中会将即将显示的fragment 调用setMaxLifecycle方法设置为 RESUMED,所以即将显示的fragment会调用onResume方法
而上一个显示的Fragmentm(CurrentPrimaryItem设)会置Lifecycle为START,由于之前设置是RESUMED且执行了onResume,超过了START的限制会回退生命周期,并执行onPause方法,然后隐藏当前实例。

生命周期:

首次进入

log: fragment1:onCreate
log: fragment2:onCreate
log: fragment1:onActivityCreated
log: fragment1:onStart
log: fragment2:onActivityCreated
log: fragment2:onStart
log: fragment1:onResume

切换到fragmet2

log: fragment1:onPause
log: fragment2:onResume

home健

log: fragment2:onPause

再次打开app

log: fragment1:onStart
log: fragment2:onStart
log: fragment2:onResume

退出页面

log: fragment1:onPause
log: fragment2:onDestroy
log: fragment2:onDestroy

instantiateItem和setPrimaryItem的调用链是:

ViewPager.setAdapter->setCurrentItemInternal->populate->addNewItem/ mAdapter.setPrimaryItem

总结

疑问一:设置STARTED后是否执行onResume?那是否能交互?
疑问二:FragmentPagerAdapter如果设置STARTED的话,就不会执行到onResume方法,懒加载就无法实现,更没有降级一说?

1、设置STARTED后是不会执行onResume,包括当前要显示的fragment,也不会影响用户交互。
2、FragmentPagerAdapter会先设置MaxLifecycle的状态为STARTED,然后执行setPrimaryItem方法时会将要显示的Fragment设置为RESUMED,故显示的Fragment会执行onResume。最后设置上一个Fragment的状态为STARTSED,并调用其的onPause方法

STARTSED状态说明:after onStart call;right before onPause call

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值