這幾天在項目中需要用到輪播圖,由于不想使用別人開源的,于是直接使用了 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 功能實現了,等等,說好的優雅 呢?你 ?逗我?
找屎.jpg
為了更優雅的實現,我可是加(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 那樣寫就可以了