通用的RecyclerView 的Adapter 多类型
都是从网上查来的,写到这里以后比较好找
多类型的适配器比单一类型的适配器多了一个多类型布局的创建和数据绑定时ItemType的辨别
先创建一个多类型的辅助类
import android.support.annotation.LayoutRes;
/**
* Created by Song on 2019/7/19 10:52
* I love you three thousand times.
*/
public abstract class MultiItemTypeSupport {
public abstract int getItemViewType(int position, T bean);
public abstract @LayoutRes
int getItemLayoutId(int type);
// public abstract void bindView(BaseViewHolder viewHolder, List list, int position);
}
然后还需要一个ViewHolder的基类
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Created by Song on 2019/7/19 11:26
* I love you three thousand times.
*/
public class BaseViewHolder extends RecyclerView.ViewHolder {
private SparseArrayCompat mViews = new SparseArrayCompat<>();
private Context mContext;
protected BaseViewHolder(Context context, View itemView) {
super(itemView);
mContext = context;
}
public static BaseViewHolder getViewHolder(Context context, ViewGroup viewGroup, @LayoutRes int layoutId) {
View itemView = LayoutInflater.from(context).inflate(layoutId, viewGroup, false);
return new BaseViewHolder(context, itemView);
}
public View getView(@IdRes int idRes) {
View v = mViews.get(idRes);
if (v == null) {
v = itemView.findViewById(idRes);
mViews.put(idRes, v);
}
return v;
}
public BaseViewHolder setTextOfTextView(@IdRes int idRes, CharSequence text) {
if (getView(idRes) instanceof TextView) {
((TextView) getView(idRes)).setText(text);
}
return this;
}
public BaseViewHolder setBackgroundOfView(@IdRes int idRes, @DrawableRes int drawableRes) {
getView(idRes).setBackgroundResource(drawableRes);
return this;
}
public BaseViewHolder setColorOfTextView(@IdRes int idRes, @ColorInt int color) {
if (getView(idRes) instanceof TextView) {
((TextView) getView(idRes)).setTextColor(color);
}
return this;
}
public BaseViewHolder setImageOfImageView(@IdRes int idRes, @DrawableRes int drawableRes) {
if (getView(idRes) instanceof ImageView) {
((ImageView) getView(idRes)).setImageResource(drawableRes);
}
return this;
}
public BaseViewHolder setImageOfImageView(@IdRes int idRes, Drawable drawable) {
if (getView(idRes) instanceof ImageView) {
((ImageView) getView(idRes)).setImageDrawable(drawable);
}
return this;
}
public BaseViewHolder setItemListener(View.OnClickListener listener) {
itemView.setOnClickListener(listener);
return this;
}
}
这时候创建适配器
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Song on 2019/7/19 10:47
* I love you three thousand times.
*/
public abstract class BaseRecyclerViewOfMultiTypeAdapter extends RecyclerView.Adapter {
private MultiItemTypeSupport itemTypeSupport;
private List mDataList;
protected Context mContext;
protected int itemType;
public BaseRecyclerViewOfMultiTypeAdapter(Context context, MultiItemTypeSupport multiItemTypeSupport, List datas) {
mContext = context;
if (datas == null) {
mDataList = new ArrayList<>();
} else {
mDataList = datas;
}
itemTypeSupport = multiItemTypeSupport;
}
@Override
public int getItemViewType(int position) {//多类型要重写
itemType = itemTypeSupport.getItemViewType(position, mDataList.get(position));
if (itemType == -1) {
throw new RuntimeException("检查resType字段的值");
}
return itemType;
}
@Override
public void onBindViewHolder(BaseViewHolder viewHolder, int i) {
bindViewHolder(viewHolder, mDataList.get(i));
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return BaseViewHolder.getViewHolder(this.mContext, viewGroup, itemTypeSupport.getItemLayoutId(i));
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemCount() {
return mDataList.size();
}
public void setDataList(List dataList) {
if (mDataList == dataList) {
notifyDataSetChanged();
return;
}
if (dataList != null) {
mDataList.clear();
mDataList.addAll(dataList);
notifyDataSetChanged();
}
}
public void addDataList(List dataList) {
if (dataList == null) return;
mDataList.addAll(dataList);
notifyDataSetChanged();
}
public void addDataBean(T dataBean) {
if (dataBean == null) return;
mDataList.add(dataBean);
notifyDataSetChanged();
}
public List getDataList() {
return mDataList;
}
public abstract void bindViewHolder(BaseViewHolder holder, T itemBean);
}
- 要注意上面所有的BaseViewHolder 都要是创建的那个ViewHolder类,不能是RecyclerView.ViewHolder
- 还有上面辅助类的T 和 适配器类的T 都是同样的数据集的类型
使用方法
先创建多布局的辅助类
public static final int ITEM_ONLY_TEXT = 1;//仅仅是文字的类型
public static final int ITEM_ONE_BIG_PICTURE = 2;//一张大图的类型
public static final int ITEM_ONE_SMALL_PICTURE = 3;//一张小图的类型
public static final int ITEM_THREE_SMALL_PICTURE = 4;//三张小图的类型
private MultiItemTypeSupport itemTypeSupport = new MultiItemTypeSupport() {
@Override
public int getItemViewType(int position, ZhimaListBeanNew.ReportInfo bean) {
//列表缩略图类型 0 一张小图、1 一张大图、2 三张小图 3纯文字
switch (bean.imgType) {
case "3":
return ITEM_ONLY_TEXT;
case "1":
return ITEM_ONE_BIG_PICTURE;
case "0":
return ITEM_ONE_SMALL_PICTURE;
case "2":
return ITEM_THREE_SMALL_PICTURE;
}
return -1;
}
@Override
public int getItemLayoutId(int type) {
if (type == -1) {
//这里直接抛出了运行异常 所以说这个 imgType 一定要是上面的几种类型中的一个 如果没有的话会崩溃 是否崩溃和后台返回数据有关
//可以处理这个异常 返回个默认的布局就好 亦或者返回个空布局只是相关的数据就没有用了(展示不出来)
throw new RuntimeException("请检查ItemViewType");
}
switch (type) {
case ITEM_ONLY_TEXT:
return R.layout.item_zhima_list_only_text;//相应的布局文件
case ITEM_ONE_BIG_PICTURE:
return R.layout.item_zhima_list_one_big_picture;
case ITEM_ONE_SMALL_PICTURE:
return R.layout.item_zhima_list_one_small_picture;
case ITEM_THREE_SMALL_PICTURE:
return R.layout.item_zhima_list_three_small_picture;
}
return -1;
}
};
然后初始化适配器
if (multiTypeAdapter == null) {
multiTypeAdapter = new BaseRecyclerViewOfMultiTypeAdapter(this, itemTypeSupport, null) {
@Override
public void bindViewHolder(final BaseViewHolder holder, final ZhimaListBeanNew.ReportInfo itemBean) {
holder.setItemListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickPosition = holder.getAdapterPosition();
//跳详情页面
Intent intent = new Intent(ActivityZhimaIndex.this, ActivityZhimaContent.class);
intent.putExtra("id", itemBean.id);
startActivity(intent);
}
});
int heightTitle = (int) (getResources().getDimension(R.dimen.dm032) - getResources().getDimension(R.dimen.dm002));
((TextView) holder.getView(R.id.tv_item_zhima_title)).setText(TextViewHelper.setLeftImage(ActivityZhimaIndex.this, R.drawable.iv_zhima_list_title, itemBean.title, heightTitle));
holder.setTextOfTextView(R.id.tv_item_zhima_content, itemBean.desc);
//需要付费并且订阅人数不为空
if ("1".equals(itemBean.needPay) && !TextUtils.isEmpty(itemBean.buyCount)) {
holder.setTextOfTextView(R.id.tv_item_zhima_left_text, itemBean.buyCount + " " + itemBean.time + " " + itemBean.ubName);
//已订阅
if ("1".equals(itemBean.hasBuy)) {
holder.setTextOfTextView(R.id.tv_item_zhima_right_text, "已购买")
.setColorOfTextView(R.id.tv_item_zhima_right_text, getResources().getColor(R.color.color69, null));
holder.getView(R.id.tv_item_zhima_right_text).setVisibility(View.VISIBLE);
Glide.with(ActivityZhimaIndex.this).load(R.drawable.iv_zhima_not_suo).into((ImageView) (holder.getView(R.id.iv_item_zhima_suo)));
holder.getView(R.id.iv_item_zhima_suo).setVisibility(View.VISIBLE);
} else {
holder.setTextOfTextView(R.id.tv_item_zhima_right_text, "解锁全文")
.setColorOfTextView(R.id.tv_item_zhima_right_text, CommonUtils.getColorAccent(ActivityZhimaIndex.this));
holder.getView(R.id.tv_item_zhima_right_text).setVisibility(View.VISIBLE);
Glide.with(ActivityZhimaIndex.this).load(R.drawable.iv_zhima_suo).into((ImageView) (holder.getView(R.id.iv_item_zhima_suo)));
holder.getView(R.id.iv_item_zhima_suo).setVisibility(View.VISIBLE);
}
} else {
holder.setTextOfTextView(R.id.tv_item_zhima_left_text, itemBean.time + " " + itemBean.ubName);
holder.getView(R.id.iv_item_zhima_suo).setVisibility(View.GONE);
holder.getView(R.id.tv_item_zhima_right_text).setVisibility(View.GONE);
}
//上面的是不同布局但是有相同部分的数据绑定
//下面就是不同布局各自的数据绑定
switch (itemType) {
case ITEM_ONLY_TEXT:
return;
case ITEM_ONE_BIG_PICTURE:
Glide.with(ActivityZhimaIndex.this).load(itemBean.img1)
.into((ImageView) holder.getView(R.id.iv_item_zhima_big_one));
return;
case ITEM_ONE_SMALL_PICTURE:
Glide.with(ActivityZhimaIndex.this).load(itemBean.img1)
.into((ImageView) holder.getView(R.id.iv_item_zhima_small_first));
return;
case ITEM_THREE_SMALL_PICTURE:
Glide.with(ActivityZhimaIndex.this).load(itemBean.img1)
.into((ImageView) holder.getView(R.id.iv_item_zhima_small_first));
Glide.with(ActivityZhimaIndex.this).load(itemBean.img2)
.into((ImageView) holder.getView(R.id.iv_item_zhima_small_second));
Glide.with(ActivityZhimaIndex.this).load(itemBean.img3)
.into((ImageView) holder.getView(R.id.iv_item_zhima_small_third));
return;
}
}
//!!!看这里 这里可能会重写适配器中的其他方法
};
}
- 在我使用的时候,因为有item复用的问题,要用到onViewRecycled 来解绑Tag,但是在重写的时候一定要注意下面代码
@Override
public void onViewRecycled(@NonNull XXX holder) {
super.onViewRecycled(holder);
}
上面的XXX 一定要是你自己写的那个ViewHolder 类,不然会报
Method does not override method from its superclass
重写错误还有在处理复用问题的时候最好使用
SparseArrayCompat
不要使用Map
之后将数据绑定的抽象方法放到辅助类里面,然后在适配器中的构造函数的参数中直接new 一个辅助类就行了,不用单独在创建辅助类对象了