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