ViewPager中预加载与懒加载

ViewPager中预加载与懒加载

预加载

为了让用户在切换过程中不卡顿,安卓官方默认创建当前item时,会创建第二个item,确保用户滑动时第二个item已经被创建,保持viewpager的平滑移动的效果。所以实现了预加载。

  • viewpager.setCurrentItem(int item)

    设置当前显示第几个item

  • viewpager.setOffscreenPageLimit(int limit)

    limit参数默认是1,即使设置为0的话,默认值也为1(非当前显示页面)

    默认是预加载当前显示item的两侧的itemview

    如果是共5个item,当前显示在第3个item,则会缓存2,4的item

    如果移动到4item,则清除2item,缓存3,5item

懒加载

如果预加载多个页面的时,由于预加载的原因,多个页面同时会对网络进行请求,造成流量浪费,卡顿等问题,懒加载解决的问题就是让页面上一些信息进行延迟加载,不至于同时进行太多并发的请求等

所以引入懒加载概念

Fragment懒加载

  • setUserVisibleHint(boolean isVisibleToUser) 方法进行懒加载的控制(老办法,存在弊端)

    之前是通过回调这个方法对页面当前显示和不显示的状态监听。

    但是这个方法会在生命周期初始化执行之前就调用,是最先执行的方法,导致第一次执行时获取的boolean是false,并不是用户已经离开页面,而是页面还未初始化。

    当执行onCreate()方法后再回调setUserVisibleHint()返回的才是真实的状态值。

    	/** 
         * 判断是否是初始化Fragment 
         */  
        private boolean hasInitFragment = false;  
        @Override  
        public void setUserVisibleHint(boolean isVisibleToUser) {  
            super.setUserVisibleHint(isVisibleToUser);  
            //fragment中执行了onCreate方法后,isVisibleToUser为true,代表页面也已经显示
            if (isVisibleToUser) {  
                hasInitFragment = true;  
                Log.i(TAG,"界面显示");  
            } else {  
                if (hasStarted) {  
                    hasInitFragment = false;  
                    Log.i(TAG,"界面不显示");  
                }  
            }  
        }  
    
  • setUserVisibleHint()方法调用缺点

    因为这个方法会在onAttach()生命周期之前最先调用,可能会造成一些控件未初始化就被调用的问题,应严格注意(比如网络请求等)

  • AndroidX下通过使用setMaxLifecycle(Fragment fragment, Lifecycle.State state)可以实现懒加载

    下文介绍总结

Viewpager懒加载

FragmentPagerAdapter与FragmentStatePagerAdapter构造方法增加了一个参数的传递

  • BEHAVIOR_SET_USER_VISIBLE_HINT

    通过回调setUserVisibleHint()方法,来判断fragment的状态的显示或隐藏

  • BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

    通过此状态位的判断,在执行instantiateItem()方法时进行判断

    通过参数的判断,来控制fragment的生命周期函数走到哪里不再继续往下执行

new ViewPagerAdapter(getSupportFragmentManager(),
                     FragmentPagerAdapter.BEHAVIOR_SET_USER_VISIBLE_HINT);
new ViewPagerAdapter(getSupportFragmentManager(),
                     FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
//根据mBehavior的状态位进行判断
if (mBehavior == BEHAVIOR_SET_USER_VISIBLE_HINT) {
    fragment.setUserVisibleHint(false);
}        
if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
    mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
}

Fragment中setMaxLifecycle使用总结

  • Lifecycle.State五种状态解释

    • INITIALIZING 初始状态
    • CREATED 已创建状态
    • ACTIVITY_CREATED 完全创建,但是没有started
    • STARTED 创建并启动,可见不可操作
    • RESUMED 创建启动并可操作

    把生命周期方法从

    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状态;

  1. 当fragment单独使用add时
  2. 使用setMaxLifecycle(Lifecycle.State.CREATED),配合add使用
  3. 使用setMaxLifecycle(Lifecycle.State.STARTED),配合add使用

  4. 使用setMaxLifecycle(Lifecycle.State.RESUMED),配合add使用

  5. 单独使用setMaxLifecycle

    • 对RESUMED状态的Fragment进行操作CREATED操作

    • 对RESUMED状态的Fragment进行操作STARTED操作

    • 对RESUMED状态的Fragment进行CREATED操作,再进行STARTED操作

    setMaxLifecycle这个方法貌似也只在FragmentPagerAdapter和FragmentStatePagerAdapter的构造方法传入的参数有用到,查看其它的文章时好像并没有看到对这个方法的调用,所以关于每个状态的详细使用暂时就不去过多记录了

    总结

    在AndroidX包下使用的懒加载方案通过使用FragmentPagerAdapter与FragmentStatePagerAdapter构造方法的第二个参数控制。

    在调用构造方法时传入下面的参数,在onResume()方法中去执行延迟加载的操作
    FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

上一篇:vue 项目, 通知子组件更新,父组件中每次点击按钮重新加载子组件,(重新生成dom 元素)


下一篇:antd form Warning: Instance created by `useForm` is not connected to any Form element. Forget to pas