ViewPager 禁止预加载(0预加载)和设置指定页为默认启动页(消除一闪而过)

1 ViewPager 禁止预加载

    要实现禁止预加载,有比较多的方式,如下

     (1)setOffscreenPageLimit(limit);

            此种方式设置的limit不得低于1,因为就算你设置低于1,api也会修改为1,这点可以点进v4包的 api追踪代码看,不做说明

     (2)实现0预加载,当前可以在网上下载别人组装好的ViewPager,其实这种组装好的ViewPager原理也比较简单,就是将v4包的ViewPager代码复制出来,要么修改ViewPager的DEFAULT_OFFSCREEN_PAGES为0,要么修改setOffscreenPageLimit(int limit)方法,最后再拉上v4包原有相匹配的的adapter以及一系列不可分离的api 最后打成jar包,调用jar包的ViewPager就可以

    (3)自定义ViewPager继承V4包的ViewPager,覆写setOffscreenPageLimit(int limit)方法,利用反射修改mOffscreenPageLimit属性,代码如下

        

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ViewPagerWithLimit extends ViewPager {
    public ViewPagerWithLimit(@NonNull Context context) {
        super(context);
    }

    public ViewPagerWithLimit(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setOffscreenPageLimit(int limit) {

        if (limit != getOffscreenPageLimit()) {
            try {
                Class c = Class.forName("android.support.v4.view.ViewPager");
                Field field =c.getDeclaredField("mOffscreenPageLimit");
                field.setAccessible(true);
                field.setInt(this, limit);
                Class clazz = this.getClass();
                Method m1 = clazz.getDeclaredMethod("populate");
                m1.invoke(this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

  再结合以下自定义Fragment

import android.content.Context;
import android.support.v4.app.Fragment;
import android.view.ViewGroup;

public abstract class CustomFragment extends Fragment {
   Context context;
   protected boolean isVisible;  //fragment界面是否呈现出来
   
   public CustomFragment() {
      // TODO Auto-generated constructor stub
   }



   @Override
   public void setUserVisibleHint(boolean isVisibleToUser) {
      super.setUserVisibleHint(isVisibleToUser);
      if(getUserVisibleHint()) {
         isVisible = true;
         onVisible();
      } else {
         isVisible = false;
         onInvisible();
      }
   }

   protected void onVisible(){
      onVisibleLoad();
   }

   protected abstract void onVisibleLoad();

   protected void onInvisible(){}
   public void destroyItem(ViewGroup container, int position, Object object) {
      //super.destroyItem(container, position, object);
   }
}

   在onVisibleLoad这个方法里,就是Fragment 对用户可见的时候执行的,onInvisible就是对于用户不可见的时候执行的

   然后 在使用Fragment的地方,继承 CustomFragment,在onCreateView方法里给标记,复写onVisibleLoad方法,判断该标记位, 代码如下   

public class UseFragment extends CustomFragment{
    // 标志位,标志已经初始化完成。
    private boolean isPrepared;  
    private int positionPage;
    public UseFragment () {
        super();
    }

     public static UseFragment newInstance(int positionPage) {
        SelectMusicFragment newFragment = new SelectMusicFragment();
        Bundle bundle = new Bundle();        
        bundle.putInt("positionPage", positionPage);
        newFragment.setArguments(bundle);
        return newFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.fragment_layout,container, false);
        Bundle bundle=this.getArguments();
        themeMusicEntitty=bundle.getParcelable("themeMusicEntitty");
        positionPage=bundle.getInt("positionPage");        
        isPrepared = true;       
        onVisibleLoad();
        return view;
    }   
   

    @Override
    protected void onVisibleLoad() {
       
        if(isPrepared&&isVisible) {
           //页面可见执行逻辑

           //页面可见执行逻辑

          //页面可见执行逻辑
        }
    }

    @Override
    public void onDestroyView() {
        isVisible=false;
        isPrepared=false;
        super.onDestroyView();
    }
}

   如果不用(3)反射的原理,仅仅是用自定义的Fragment ,你会发现,在指定下标页为启动页的时候,该下标页的前面一页,照样执 行onCreateView(),原因是因为 ViewPager默认执行 1个预加载

 viewPager.setOffscreenPageLimit(0);则表示预加载0个

至此 自己修改预加载的方式结束,下面将介绍 设置指定页为默认启动页,

1,设置指定页为默认启动页

   (1)调用api的方式

       viewpager.setCurrentItem(index);此种方式虽然可以设置默认启动下标页,但是系统会首先加载第0个,然后再滑到index页面,会有一闪而过的现象

   (2)利用反射,直接设置默认启动页,不会从第0个滑到指定index,代码如下

   

 private void setDefaultItem(int position){
        try {
            Class c = Class.forName("android.support.v4.view.ViewPager");
            Field field =c.getDeclaredField("mCurItem");
            field.setAccessible(true);
            field.setInt(viewPager, position);
        } catch (Exception e) {
            e.printStackTrace();
        }     
    }

 在调用 viewPager.setAdapter(adapter);之前调用setDefaultItem(position)即可,这样viewpager将直接认为posion为第一个启动页,而不会产生 一闪而过的尴尬,再结合上面说到的禁止预加载,可以很好的实现界面ui和逻辑加载分离

如果想设置预加载为0个,再设置页面缓存number个,也是支持的 ,代码如下

/**
 * 200毫秒后设置页面缓存fragmentList.size()个
 */
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        viewPager.setOffscreenPageLimit(number);
    }
},200);

      

当然了,考虑到有些同行比较忙,不想看这么多文字解释,还是代码片段的,这里也做好了一个demo供大家下载,更直接了当,

demo有些注释部分是我项目里的,可能没删干净,又没法重新修改资源包,不过也不碍事,你自动忽略掉就行了。点击下面链接下载即可

https://download.csdn.net/download/t7g367/12461878

 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

零九

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

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

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

打赏作者

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

抵扣说明:

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

余额充值