美文网首页
RecyclerView-->通用的Adapter

RecyclerView-->通用的Adapter

作者: 谢尔顿 | 来源:发表于2018-10-12 14:51 被阅读24次

打造一个通用的Adapter,可以减少我们的代码量,通用的Adapter需要我们考虑三个问题:

  • 数据的类型?我们可以采用泛型;
  • 布局?我们可以利用构造函数传递;
  • 绑定?利用回传,让子类实现;

1.Adapter的基本改造

通用Adapter的代码如下:

public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
    protected Context mContext;
    protected LayoutInflater mInflater;
    protected List<T> mDatas;
    private int mLayoutId;

    public CommonRecyclerAdapter(Context context, List<T> datas, int layoutId) {
        this.mContext = context;
        this.mInflater = LayoutInflater.from(mContext);
        this.mDatas = datas;
        this.mLayoutId = layoutId;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = mInflater.inflate(mLayoutId, parent, false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        if (mDatas != null){
            convert(holder, mDatas.get(position),position);
        }else {
            convert(holder, null,position);
        }
    }

    /**
     * 利用抽象方法回传出去,每个不一样的Adapter去设置
     * @param item 当前的数据
     */
    public abstract void convert(ViewHolder holder, T item,int position);

    @Override
    public int getItemCount() {
        return mDatas == null ? 20:mDatas.size();
    }
}

实际使用如下:

public class TestAdapter extends CommonRecyclerAdapter<String> {



    public TestAdapter(Context context, List<String> datas) {
        super(context,datas,R.layout.item_demo);
    }
    @Override
    public void convert(ViewHolder viewHolder, String bean, int position) {
        TextView text = (TextView)viewHolder.itemView.findViewById(R.id.tv_text);
        text.setText(String.format("第%d数据", position + 1));
    }

}

可以看到代码量大大滴减少了。

但是上面使用中我们发现每次调用onBindViewHolder都会findViewById,所以我们还需要对ViewHolder进行优化。

2.ViewHolder的优化

优化后的ViewHolder如下:

public class ViewHolder extends RecyclerView.ViewHolder {

    //用来存放view减少findviewByid的次数
    private SparseArray<View> mViews;
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        mViews = new SparseArray<>();
    }

    /**
     * 设置TextView文本
     * @param viewId
     * @param text
     * @return
     */
    public ViewHolder setText(int viewId,CharSequence text){
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    public <T extends  View> T getView(int viewId){
        View view = mViews.get(viewId);
        if (view == null){
            view = itemView.findViewById(viewId);
            mViews.put(viewId,view);
        }

        return (T)view;
    }

    /**
     * 设置view是否可见
     * @param viewId
     * @param visibility
     * @return
     */
    public ViewHolder setViewVisibility(int viewId,int visibility){
        getView(viewId).setVisibility(visibility);
        return this;
    }

    /**
     * 设置ImageView资源
     * @param viewId
     * @param resId
     * @return
     */
    public  ViewHolder setImageResourse(int viewId,int resId){
        ImageView imageView = getView(viewId);
        imageView.setImageResource(resId);
        return this;
    }

    /**
     * 设置条目的点击事件
     * @param listener
     */
    public void setOnItemClickListener(View.OnClickListener listener){
        itemView.setOnClickListener(listener);
    }

    /**
     * 设置图片通过url,加载图片使用的第三方可能不一样,所以定义了HolderImageLoader
     * @param viewId
     * @param imageLoader
     */
    public void setImageByUrl(int viewId,HolderImageLoader imageLoader){
        ImageView imageView = getView(viewId);
        if (imageLoader == null){
            throw  new NullPointerException("imageLoader is null!");
        }
        imageLoader.displayImage(imageView.getContext(),imageView,imageLoader.getImagePath());
    }
    /**
     * 设置条目的长按事件
     * @param listener
     */
    public void setOnItemLongClickListener(View.OnLongClickListener listener){
        itemView.setOnLongClickListener(listener);
    }

    public static abstract class HolderImageLoader{
        private String mImagePath;
        public HolderImageLoader(String imagePath){
            this.mImagePath = imagePath;
        }
        public String getImagePath(){
            return mImagePath;
        }

        public abstract void displayImage(Context context,ImageView imageView,String imagePath);
    }
}

实际使用:

public class TestAdapter extends CommonRecyclerAdapter<String> {
    
    public TestAdapter(Context context, List<String> datas) {
        super(context,datas,R.layout.item_demo);
    }
    @Override
    public void convert(ViewHolder viewHolder, String bean, int position) {
        viewHolder.setText(R.id.tv_text,String.format("第%d数据", position + 1))
    }

}

3.多布局的实现

public interface MultiTypeSupport<T> {
    public int getLayoutId(T bean,int position);
}

最终的Adapter:

public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
    protected Context mContext;
    protected LayoutInflater mInflater;
    protected List<T> mDatas;
    private int mLayoutId;
    //多布局支持
    private MultiTypeSupport mMultiTypeSupport;

    public CommonRecyclerAdapter(Context context, List<T> datas, int layoutId) {
        this.mContext = context;
        this.mInflater = LayoutInflater.from(mContext);
        this.mDatas = datas;
        this.mLayoutId = layoutId;
    }

    //多布局支持
    public CommonRecyclerAdapter(Context context, List<T> datas, MultiTypeSupport multiTypeSupport) {
        this(context, datas, -1);
        mMultiTypeSupport = multiTypeSupport;
    }

    @Override
    public int getItemViewType(int position) {
        if (mMultiTypeSupport != null)
            return mMultiTypeSupport.getLayoutId(mDatas.get(position), position);
        return super.getItemViewType(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mMultiTypeSupport != null)
            mLayoutId = viewType;
        View itemView = mInflater.inflate(mLayoutId, parent, false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        if (mItemClickListener != null) {
            holder.setOnItemClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mItemClickListener.OnItemClick(position);
                }
            });
        }

        if (mLongClickListener != null) {
            holder.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    return mLongClickListener.onLongClick(position);
                }
            });
        }
        if (mDatas != null) {
            convert(holder, mDatas.get(position), position);
        } else {
            convert(holder, null, position);
        }
    }

    /**
     * 利用抽象方法回传出去,每个不一样的Adapter去设置
     *
     * @param item 当前的数据
     */
    public abstract void convert(ViewHolder holder, T item, int position);

    @Override
    public int getItemCount() {
        return mDatas == null ? 20 : mDatas.size();
    }

    /***************
     * 设置条目点击和长按事件
     *********************/
    public OnItemClickListener mItemClickListener;
    public OnLongClickListener mLongClickListener;

    public void setOnItemClickListener(OnItemClickListener itemClickListener) {
        this.mItemClickListener = itemClickListener;
    }

    public void setOnLongClickListener(OnLongClickListener longClickListener) {
        this.mLongClickListener = longClickListener;
    }

    public interface OnItemClickListener {
        void OnItemClick(int position);
    }

    public interface OnLongClickListener {
        boolean onLongClick(int position);
    }

}

相关文章

网友评论

      本文标题:RecyclerView-->通用的Adapter

      本文链接:https://www.haomeiwen.com/subject/jcmwaftx.html