AndroidX对ViewPager懒加载的影响及解决方案

本文探讨AndroidX迁移后对ViewPager懒加载造成的影响,主要体现在FragmentPagerAdapter的初始化方式变化。旧版使用BEHAVIOR_SET_USER_VISIBLE_HINT,而AndroidX推荐使用BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,导致Fragment的生命周期改变。解决方案是根据onResume()而非setUserVisibleHint()判断页面状态。文章还提到BaseFragment的相应调整,并鼓励读者参考相关资源进行深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要是讲解迁移到AndroidX之后,对原本的ViewPager懒加载造成的影响,和如何进行优化。参考的项目来自

波澜步惊 的文章 《手把手讲解 ViewPager懒加载》

最后的代码修改对比也是来自大神的文章,建议先看一下再过来看本文

一、为什么要迁移为AndroidX

根据官方说明,AndroidX是对原始Android支持库(android.support.*)进行了重大改进和统一管理,旧的库依然能用,但是新库的开发都将会在AndroidX中进行,所以建议还是迁移到AndroidX。

1859102-0c92af02302cead3.png

具体如何迁移,本文在此不做详细说明,请查看官方文档

二、迁移之后的区别

迁移之后出现问题,主要是因为FragmentPagerAdapter的文件有所改动

1 初始化

旧版:

1859102-e2164797dad0297e.png

新版:

1859102-458d8a8c663c43af.png

可以看到初始化的方式添加了一个@Deprecated (废弃)的注解,就是告诉大家不要用这种方式进行初始化了。那么应该怎么进行初始化呢?

1859102-adeef343dc852031.png

这里就可以看到,初始化的时候,除了需要传入fm,同时还需要传一个behavior,让我们来看看Behavior具体是哪些值?

1859102-59d1d66d10e26b71.png

根据注释可以知道

当behavior == BEHAVIOR_SET_USER_VISIBLE_HINT 时,Fragment切换时,会触发setUserVisibleHint。
这个效果和[图片上传失败...(image-498b78-1587693534449)]

的效果一样,也就是说,如果你不想修改原来懒加载的逻辑,只需要这么写

FragmentPagerAdapter adapter = new FragmentPagerAdapter(fm);
或者
FragmentPagerAdapter adapter = new FragmentPagerAdapter(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);

但是,我们看到了BEHAVIOR_SET_USER_VISIBLE_HINT也被标识了@Deprecated (废弃),建议我们使用BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT。所以[图片上传失败...(image-7fe658-1587693534449)]

初始化方式是:

FragmentPagerAdapter adapter = new FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

而这时候会用到生命周期状态标识Lifecycle.State。

2 FragmentPageAdapter初始化Fragment

@NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        //...省略非重点代码 
        if (mBehavior == BEHAVIOR_SET_USER_VISIBLE_HINT) {
            //旧版本,触发setUserVisibleHint
            fragment.setUserVisibleHint(false);
        }

        mFragments.set(position, fragment);
        //关键句,添加Fragment进入事物list
        mCurTransaction.add(container.getId(), fragment);

        if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
            //AndroidX,设置初始化执行到onStart()就停止了
            mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
        }

        return fragment;
    }

追踪进入mCurTransaction.add(container.getId(), fragment);方法

1859102-d69c715aa72863cd.png
 void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
    //...省略非重点代码
     addOp(new Op(opcmd, fragment));
 }

1859102-123bae0b9bd3c8a4.png

添加的是一个Op对象,看看Op是如何初始化的。

Op(int cmd, Fragment fragment) {
            this.mCmd = cmd;
            this.mFragment = fragment;
            //初始化执行到onResume()
            this.mOldMaxState = Lifecycle.State.RESUMED;
            this.mCurrentMaxState = Lifecycle.State.RESUMED;
        }

到这里,我们就能明白了如果是旧版本,Fragment初始化的时候,默认会执行到onResume(),而AndroidX只会执行到onStart(),所以我们迁移到AndroidX之后,不需要全都依靠setUserVisibleHint()来判断当前页面是否显示,我们可以根据onResume()来判断。

3 迁移到AndroidX之后,BaseFragment相应的修改

@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRoot = inflater.inflate(getLayoutId(), container, false);
        Log.d(getLifeCycleTag(), "onCreateView");
        initView(mRoot);
        //在View创建完毕之后,isViewCreate 要变为true
        isViewCreated = true;
        //下面2段代码可以删除
        //if (!isHidden() && getUserVisibleHint())
            //dispatchVisibleState(true);
        return mRoot;
    }

@Override
    public void onResume() {
        super.onResume();
        Log.d(getLifeCycleTag(), "onResume");
       /* 旧版本
        if (!isFirstVisible) {
            if (!isHidden() && !currentVisibleState && getUserVisibleHint())
                dispatchVisibleState(true);
        }
        */
        //新版本
        if (!isHidden() && !currentVisibleState && isResumed()) {
            dispatchVisibleState(true);
        }
    }

@Override
    public void onPause() {
        MobclickAgent.onPageEnd(this.getClass().getName());
        super.onPause();
        Log.d(tag,"onPause: ");
        /* 旧版本
        if (currentVisibleState && !isResumed()) {
            dispatchVisibleState(false);
        }
        */
        //新版本
        if (currentVisibleState && !isResumed()) {
            dispatchVisibleState(false);
        }
    }
//其他不需要更改

三、总结

迁移到AndroidX,主要改变的是FragmentPagerAdapter对Fragment的初始化方式进行了优化,所以才需要进行这样修改,其实问题不难,顺着逻辑看一下源码就能发现区别啦。希望对大家有所帮助,如果文章有不足之处,请不吝指出,谢谢。

四、鸣谢

感谢 波澜步惊 的文章 《手把手讲解 ViewPager懒加载》ViewPager懒加载写得很详细,易懂。

感谢 享学课堂 avlin老师 提供的demo 以及视频

作者:dasamanren
链接:https://www.jianshu.com/p/94515681e335

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值