这几天在项目中需要用到轮播图,由于不想使用别人开源的,于是直接使用了 ViewPager 来实现了,ViewPager 实现轮播图这里就不赘述了
开始的时候是直接继承的 PagerAdapter
public class BannerAdapter extends PagerAdapter {
private Context mContext;
private List<BannerBean> mDataList;
public BannerAdapter(Context context) {
this.mContext = context;
}
public void setDataList(List<BannerBean> dataList) {
this.mDataList = dataList;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
final BannerBean bean = mDataList.get(position % mDataList.size());
View rootView = View.inflate(mContext, R.layout.xxx, null);
container.addView(rootView);
return rootView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
很简单,在 getCount() 函数里,返回 Integer.MAX_VALUE ,其他函数正常写即可
但是这样会存在一个问题,在 ViewPager 不停的滚动的时候,就会不停的调用 instantiateItem() 函数,这就会导致不停的 inflate 新的 View,这样是十分不好的
首先想到的就是 itemView 复用,当然,实现复用也是很简单的,看下面
// 缓存 list
private LinkedList<View> mViewCache = new LinkedList<>();
@Override
public Object instantiateItem(ViewGroup container, int position) {
View convertView = null;
if (mViewCache.size() == 0) {
convertView = mLayoutInflater.inflate(R.layout.xxx, null, false);
} else {
convertView = mViewCache.removeFirst();
}
container.addView(convertView);
return convertView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View contentView = (View) object;
container.removeView(contentView);
mViewCache.add(contentView);
}
OK 功能实现了,等等,说好的优雅 呢?你 ™逗我?
为了更优雅的实现,我可是加(huó)班(gāi)半个多小时,连写带自测才搞定
Talk is cheap. Show me the code
/**
* 仿照 recyclerview.adapter 实现的具有 item view 复用功能的 PagerAdapter
*/
public abstract class ReusePagerAdapter<VH extends ReusePagerAdapter.Holder> extends PagerAdapter {
private SparseArray<LinkedList<VH>> holders = new SparseArray<>(1);
/**
* 获取 item count
*
* @return count
*/
public abstract int getItemCount();
/**
* 获取 view type
*
* @param position position
* @return type
*/
public int getItemViewType(int position) {
return 0;
}
/**
* 创建 holder
*
* @param parent parent
* @param viewType type
* @return holder
*/
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
/**
* 绑定 holder
*
* @param holder holder
* @param position position
*/
public abstract void onBindViewHolder(VH holder, int position);
@Override
public int getCount() {
return getItemCount();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 获取 position 对应的 type
int itemViewType = getItemViewType(position);
// 根据 type 找到缓存的 list
LinkedList<VH> holderList = holders.get(itemViewType);
VH holder;
if (holderList == null) {
// 如果 list 为空,表示没有缓存
// 调用 onCreateViewHolder 创建一个 holder
holder = onCreateViewHolder(container, itemViewType);
holder.itemView.setTag(R.id.holder_id, holder);
} else {
holder = holderList.pollLast();
if (holder == null) {
// 如果 list size = 0,表示没有缓存
// 调用 onCreateViewHolder 创建一个 holder
holder = onCreateViewHolder(container, itemViewType);
holder.itemView.setTag(R.id.holder_id, holder);
}
}
holder.position = position;
holder.viewType = itemViewType;
// 调用 onBindViewHolder 对 itemView 填充数据
onBindViewHolder(holder, position);
container.addView(holder.itemView);
return holder.itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
VH holder = (VH) view.getTag(R.id.holder_id);
int itemViewType = holder.viewType;
LinkedList<VH> holderList = holders.get(itemViewType);
if (holderList == null) {
holderList = new LinkedList<>();
holders.append(itemViewType, holderList);
}
// 缓存 holder
holderList.push(holder);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
public static abstract class Holder {
public View itemView;
public int viewType;
public int position;
public Holder(View view) {
if (view == null) {
throw new IllegalArgumentException("itemView may not be null");
}
itemView = view;
}
}
}
holder 要保存在 itemView 的 tag 中,为了防止冲突,需要指定一个 id
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="holder_id" type="id" />
</resources>
子类在继承 ReusePagerAdapter 的时候,可以直接像写 RecyclerView 的 Adapter 那样写就可以了