Android ViewPager2 setOffscreenPageLimit预加载Fragment,Kotlin

Android ViewPager2 setOffscreenPageLimit预加载Fragment,Kotlin

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2


class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "fly"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mViewPager2 = findViewById<ViewPager2>(R.id.vp2)
        mViewPager2.adapter = MyPageAdapter(this)
    }

    class MyPageAdapter : FragmentStateAdapter {
        private var mFragments = arrayListOf<MyFragment>()

        constructor(activity: FragmentActivity) : super(activity) {
            for (i in 0 until 5) {
                mFragments.add(MyFragment(i))
            }
        }

        override fun getItemCount(): Int {
            return mFragments.size
        }

        override fun createFragment(position: Int): Fragment {
            return mFragments[position]
        }
    }

    class MyFragment : Fragment {
        private var seq = 0

        constructor(seq: Int) {
            this.seq = seq
            Log.d(TAG, "$seq constructor")
        }

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.d(TAG, "$seq onCreate")
        }

        override fun onResume() {
            super.onResume()
            Log.d(TAG, "$seq onResume")
        }

        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater.inflate(android.R.layout.simple_list_item_1, container, false)
        }

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            val tv = view.findViewById<TextView>(android.R.id.text1)
            tv.text = "$seq"
            tv.textSize = 50f
            Log.d(TAG, "$seq onViewCreated")
        }

        override fun onPause() {
            super.onPause()
            Log.d(TAG, "$seq onPause")
        }

        override fun onDestroy() {
            super.onDestroy()
            Log.d(TAG, "$seq onDestroy")
        }

        override fun onDestroyView() {
            super.onDestroyView()
            Log.d(TAG, "$seq onDestroyView")
        }
    }
}

ViewPager2与ViewPager不同,默认情况下,由于ViewPager2内部源代码中mOffscreenPageLimit默认等于-1:

    public static final int OFFSCREEN_PAGE_LIMIT_DEFAULT = -1;

所以,当ViewPager2装载好Fragment启动后,只会显示当前可见的那1个Fragment,而不像过去的ViewPager那样,把后面不可见的Fragment也加载出来:

0 constructor
1 constructor
2 constructor
3 constructor
4 constructor
0 onCreate
0 onViewCreated
0 onResume

日志显示,只加载了当前可见的0号Fragment,没有加载1号Fragment。

此时,往左滑,使得1号Fragment显示在屏幕:

1 onCreate
1 onViewCreated
0 onPause
1 onResume

Fragment 1此时才创建,没有加载不可见的2号Fragment。

简单的说,这就是过去VIewPager时代,想要实现的“懒加载”模式:让ViewPager只加载当前可见的那个Fragment。而在ViewPager2中,默认情况不设置

mOffscreenPageLimit

时候,ViewPager2就是懒加载模式的ViewPager标准实现,只会加载当前显示的那1个Fragment,不会加载后面不可见的Fragment。


如果,设置了mOffscreenPageLimit呢?给mOffscreenPageLimit设置0或者-1?看看ViewPager2中的setOffscreenPageLimit()源代码:

    public void setOffscreenPageLimit(@OffscreenPageLimit int limit) {
        if (limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT) {
            throw new IllegalArgumentException(
                    "Offscreen page limit must be OFFSCREEN_PAGE_LIMIT_DEFAULT or a number > 0");
        }
        mOffscreenPageLimit = limit;
        // Trigger layout so prefetch happens through getExtraLayoutSize()
        mRecyclerView.requestLayout();
    }

已知的是OFFSCREEN_PAGE_LIMIT_DEFAULT=-1。从源代码可以看到,ViewPager2的setOffscreenPageLimit()只接受 >= 1的值,看来不能给mOffscreenPageLimit设置0或者-1。

现在给ViewPager2的设置1:

mViewPager2.offscreenPageLimit = 1

重新编译,看看启动后装载Fragment的表现:

0 constructor
1 constructor
2 constructor
3 constructor
4 constructor
0 onCreate
0 onViewCreated
0 onResume
1 onCreate
1 onViewCreated

除了加载当前可见的0号Fragment外,ViewPager2也把不可见的、后面1号Fragment顺带加载出来了,这和过去老版ViewPager相同。

往左滑一个页面,把1号Fragment显示出来当前可见:

2 onCreate
2 onViewCreated
0 onPause
1 onResume

调用了1号Fragment的onResume周期方法,并把不可见的2号Fragment创建出来。

如果offscreenPageLimit 是2:

mViewPager2.offscreenPageLimit = 2

编译重新启动后:

0 constructor
1 constructor
2 constructor
3 constructor
4 constructor
0 onCreate
0 onViewCreated
0 onResume
1 onCreate
1 onViewCreated
2 onCreate
2 onViewCreated

除了把当前可见的0号Fragment加载出来外,还把不可见的1号和2号Fragment也加载出来了。


总结:

1、ViewPager2默认不设置mOffscreenPageLimit情况下,就是过去老版ViewPager想要达到的“懒加载”“延迟加载”模式,即,只加载当前可见的那1个Fragment。

2、如果设置了mOffscreenPageLimit(并且,mOffscreenPageLimit通过setOffscreenPageLimit()这个API接口也只能设置  >=1 的值),ViewPager2就退化成过去老版的ViewPager了,除了把当前可见的那个Fragment加载出来外,还会根据用户设置的mOffscreenPageLimit值,加载mOffscreenPageLimit个不可见的Fragment。即一次性总共加载 1 + mOffscreenPageLimit 个Fragment。1是当前屏幕显示的那1个Fragment;mOffscreenPageLimit是后面不可见的Fragment。

ViewPager2和Fragment可见性及懒加载解决方案_viewpage2和fragment 当前页面可见接受消息-CSDN博客文章浏览阅读6.5k次,点赞5次,收藏14次。ViewPager2和Fragment新的可见性及懒加载解决方案,旨在解决ViewPager(ViewPager2)只有当前Fragment唯一可见时候网络刷新或绘图。注意:过去的setUserVisibleHint()已被废弃,开发者不要再使用基于setUserVisibleHint()解决Fragment可见性和懒加载(或延迟加载)的场景。新方案用最新的ViewPager2替代过去旧版的ViewPager,再结合Fragment的resume和pause生命周期实现。写一个demo例子,测试的主类M_viewpage2和fragment 当前页面可见接受消息https://blog.csdn.net/zhangphil/article/details/108893237Android ViewPager2 load once when fast scroll many page,Java-CSDN博客文章浏览阅读206次。ViewPager2和Fragment新的可见性及懒加载解决方案,旨在解决ViewPager(ViewPager2)只有当前Fragment唯一可见时候网络刷新或绘图。注意:过去的setUserVisibleHint()已被废弃,开发者不要再使用基于setUserVisibleHint()解决Fragment可见性和懒加载(或延迟加载)的场景。新方案用最新的ViewPager2替代过去旧版的ViewPager,再结合Fragment的resume和pause生命周期实现。写一个demo例子,测试的主类M。https://blog.csdn.net/zhangphil/article/details/129885331Android ViewPager2嵌套RecyclerView性能优化RecycledViewPool,kotlin-CSDN博客文章浏览阅读750次。ViewPager2和Fragment新的可见性及懒加载解决方案,旨在解决ViewPager(ViewPager2)只有当前Fragment唯一可见时候网络刷新或绘图。注意:过去的setUserVisibleHint()已被废弃,开发者不要再使用基于setUserVisibleHint()解决Fragment可见性和懒加载(或延迟加载)的场景。ViewPager2和Fragment可见性及懒加载解决方案_viewpager2 懒加载_zhangphil的博客-CSDN博客。_viewpager2嵌套recyclerviewhttps://blog.csdn.net/zhangphil/article/details/131231747

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangphil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值