打造通用的RecyclerView的Adapter

本文并不算完全的原创,因为曾经受到某个博客的启发,可是那地址早就不记得了。

相信大家都知道listview中的item需要缓存,这样避免消耗更少的资源,所以,打造通用的RecyclerView的Adapter必须先从ViewHolder下手,那item的控件如何缓存起来呢?然后就不用findbyid,可能一些人想到可以根据HashMap键值对,根据控件的id和控件来存起来,这个也是对的,但是Android更推荐我们使用SparseArray,好了,废话不多说,直接上代码。

private  final SparseArray<View> mViews=new SparseArray<>() ;
private View mConvertView;
private Context context;
public ViewHolder(Context context,ViewGroup parent,View itemView) {
    super(itemView);
    mConvertView=itemView;
    this.context=context;
}
/**
 * 通过控件的Id获取对于的控件,如果没有则加入views
 * @param viewId
 * @return
 */
public <T extends View> T getView(int viewId) {
    View view = mViews.get(viewId);
    if (view == null) {
        view = mConvertView.findViewById(viewId);
        mViews.put(viewId, view);
    }
    return (T) view;
}
public View getConvertView() {
    return mConvertView;
}
/**
 * 为TextView设置字符串
 *
 * @param viewId
 * @param text
 * @return
 */
public ViewHolder setText(int viewId, String text) {
    TextView view = getView(viewId);
    view.setText(text);
    return this;
}
/**
 * 为ImageView设置图片
 *
 * @param viewId
 * @param drawableId
 * @return
 */
public ViewHolder setImageResource(int viewId, int drawableId)
{
    ImageView view = getView(viewId);
    view.setImageResource(drawableId);

    return this;
}

/**
 * 为ImageView设置图片
 *
 * @param viewId
 * @param
 * @return
 */
public ViewHolder setImageBitmap(int viewId, Bitmap bm)
{
    ImageView view = getView(viewId);
    view.setImageBitmap(bm);
    return this;
}
}
代码没什么好讲的,相信大家都看得懂,最主要的核心就是这个代码

public <T extends View> T getView(int viewId) {
    View view = mViews.get(viewId);
    if (view == null) {
        view = mConvertView.findViewById(viewId);
        mViews.put(viewId, view);
    }
    return (T) view;
}
如果view不存在,就findViewById,否则就直接从 SparseArray取出来,也就是说,在第一个item加载进来的时候是需要findViewById的,然后从第二个开始就是不需要了,那么问题就来了。假设你的数据源中,第一个item是需要设置图片的,第二个item是不需要设置图片,如果你没有做处理,你会发现,第二个item和第一个item都是同一张图片,或者第一个item设置属性GONE,你会发现以后的item中都是GONE的,为什么呢?就像前面说的,加载第一个item的时候是findViewById,第二个就是从SparseArray取出来的,也就是说第一个item和第二个item的控件是同一个对象,你一直操作同一个对象,自然属性也是同步的。解决的办法就自然不需要我都说了。

最后是

public abstract class CommonAdapter<T> extends RecyclerView.Adapter<ViewHolder>{
    private Context context;
    protected List<T> listData;
    private int layoutId;
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_NORMAL = 1;
    private static final  int TYPE_FOOT=2;
    public List<T> getListData() {
        return listData;
    }

    private boolean isHaveFoot;
    public CommonAdapter(Context context, List<T> listData, int layoutId) {
        this.context = context;
        this.listData = listData;
        this.layoutId = layoutId;
    }
    /**
     * 创建ViewHolder
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(context).inflate(layoutId,parent,false);
        return new ViewHolder(context,parent,view);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
       initDataView(holder, listData.get(position), position);;
    }

    /**
     * 尾部是默认有的。
     * @return
     */
    @Override
    public int getItemCount() {
      
	listData.size();
} public abstract void initDataView(ViewHolder holder,T item,int position); public void reMoveAllData(){ if (listData!=null)listData.clear(); this.notifyDataSetChanged(); } /** * 增加数据 * @param list */ public void addData(List<T> list){ if (listData!=null){ listData.addAll(list); }else{ listData=list; } this.notifyDataSetChanged(); } //更新数据 public void updateData(List<T> list){ listData=list; } /** * 重写getItemType 用来标记是否为头部 * @param position * @return */ @Override public int getItemViewType(int position) { return TYPE_NORMAL; }}
细心的同学会发现为什么定义了

 private static final int TYPE_HEADER = 0;
 private static final int TYPE_NORMAL = 1;
 private static final  int TYPE_FOOT=2;
这三个。这三个是区别头部和脚部的,如果你的需要头部刷新动画,或者脚步加载更多,这个还需要继续写,本次就先不讲这些了。上面的代码也还算简单,adapter先执行 onCreateViewHolder的方法,然后再绑定数据 onBindViewHolder,我们只需要写个抽象方法,让子类必须去实现数据源的绑定,这样就可以达到通用的目的了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值