前言:之前公司实现了一个在线作业功能,要求是有多种题型,多道题。一看需求的时候,我就确定要使用ViewPager实现。方便快捷顶呱呱,然而~~~问~~~题~~~来~~~了。
测试完后,发现的问题有:
(1)在一些机型上出现内存溢出的问题;
(2)用起来感觉非常笨重;
(3)滑动不是很流畅;
先说说我之前实现的方式:
根据题目的个数创建出对应的View(也就是说有50道题,就创建50个view),然后放到List中,直接setAdapter即可。
出现上面的问题,很可能是跟这种实现方式有关,所以决定换一种方式实现。
方式一: list中只存放5中题型的View,在adapter中根据type值获取相应的View。
结果在Viewpager滑动的时候出现异常:
字面的意思是view已经有一个parent了,要想用这个view的话得删除掉当前的parent;
然后在网上乱找一通,还是没有解决!放弃!放弃!放弃!
方式二:使用RecycleView 设置成横向滑动,就能解决这个复用的问题了。
在使用的时候出现1个问题:发现滑动使用有些卡顿;
方式三:使用对象池
对象池可以解决 创建多个对象导致内存升高的问题;
我创建了两个对象,分别代表了两种题型,直接上代码:
public class ViewTypeAEntity {
public View view;
private static final Pools.SynchronizedPool<ViewTypeAEntity> instance = new Pools.SynchronizedPool<>(3);
public static ViewTypeAEntity obtain(View contentView) {
ViewTypeAEntity viewTypeBean = instance.acquire();
if(viewTypeBean != null){
return viewTypeBean;
}else{
viewTypeBean = new ViewTypeAEntity();
viewTypeBean.view = contentView;
return viewTypeBean;
}
}
public void recycle() {
instance.release(this);
}
}
创建一个对象池;
创建一个方法用于返回对象;
还有一个对象回收的方法;
在PagerAdapter上使用:
public class PagesAdapter extends PagerAdapter {
private Context context;
private Map<Integer, Object> newsHash;
public PagesAdapter(Context context) {
newsHash = new HashMap<>();
this.context = context;
}
@Override
public int getCount() {
return 6;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int index = position % 2;
View contentView = null;
if (index == 0) {
View view = LayoutInflater.from(context).inflate(R.layout.view_a, null);
ViewTypeAEntity viewTypeAEntity = ViewTypeAEntity.obtain(view);
contentView = viewTypeAEntity.view;
newsHash.put(position, viewTypeAEntity);
} else {
View view = LayoutInflater.from(context).inflate(R.layout.view_b, null);
ViewTypeBEntity viewTypeBEntity = ViewTypeBEntity.obtain(view);
contentView = viewTypeBEntity.view;
newsHash.put(position, viewTypeBEntity);
}
container.addView(contentView);
return contentView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
int index = position % 2;
View view = null;
if (index == 0) {
ViewTypeAEntity viewTypeAEntity = (ViewTypeAEntity) newsHash.get(position);
view = viewTypeAEntity.view;
container.removeView(view);
viewTypeAEntity.recycle();
} else {
ViewTypeBEntity viewTypeBEntity = (ViewTypeBEntity) newsHash.get(position);
view = viewTypeBEntity.view;
container.removeView(view);
viewTypeBEntity.recycle();
}
}
}
注意看instantiateItem():
创建了一个对象来使用;
既然有创建就有回收,我创建了一个Map,键为position,值为创建的对象。
destroyItem()中拿到对象,回收对象;