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