用注解打造一个简易的RecyclerView Adapter

CommonViewHolder 先上一下这个全世界都在用的代码

public class CommonViewHolder extends ViewHolder {
    private SparseArray<View> sparseArray = null;

    public CommonViewHolder(View itemView) {
        super(itemView);
    }

    public View getView(int viewId) {
        if (sparseArray == null) {
            sparseArray = new SparseArray<>();
        }
        View v = null;
        View viewGot = sparseArray.get(viewId);
        if (viewGot == null) {
            v = itemView.findViewById(viewId);
            sparseArray.put(viewId, v);
            return v;
        } else {
            return viewGot;
        }
    }

    public CommonViewHolder setText(int layoutId, String s) {
        TextView tv = (TextView) getView(layoutId);
        tv.setText(s);
        return this;
    }

    public CommonViewHolder setImageBitmap(Context context, int layoutId, int drawableId) {
        ImageView iv = (ImageView) getView(layoutId);
        iv.setImageBitmap(((BitmapDrawable)context.getResources().getDrawable(drawableId)).getBitmap());
        return this;
    }

    public CommonViewHolder glide(Context context, int layoutId, String picUrl) {
        Glide.with(context).load(picUrl).into((ImageView)getView(layoutId));
        return this;
    }

    public CommonViewHolder setOnClickListener(int layoutId, View.OnClickListener l) {
        getView(layoutId).setOnClickListener(l);
        return this;
    }

    public CommonViewHolder setOnClickListener(View.OnClickListener l) {
        itemView.setOnClickListener(l);
        return this;
    }
}


下面的注解打造的Adapter用的人就几乎没有了,你可以从这里开启你的旅程

注解的声明

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ItemLayoutId {
    int itemLayoutId() default -1;
}


CommonAdapter

public abstract class CommonAdapter<T> extends RecyclerView.Adapter<CommonViewHolder>{

    @Override
    public CommonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        return new CommonViewHolder(LayoutInflater.from(context).inflate(getClass().getAnnotation(ItemLayoutId.class).itemLayoutId(), parent, false));
    }

    @Override
    public void onBindViewHolder(CommonViewHolder holder, int position) {
        onBindViewHolder(holder, getDataSource().get(position), position);
    }

    @Override
    public int getItemCount() {
        List<T> dataSource = getDataSource();
        return dataSource == null ? 0 : dataSource.size();
    }

    protected abstract List<T> getDataSource();

    protected abstract void onBindViewHolder(CommonViewHolder holder, T t, int position);
}


使用

@ItemLayoutId(itemLayoutId = R.layout.item_rv_type)
class Adapter extends CommonAdapter<HomeEntity.ListCategoryInfoVoBean> {

    @Override
    protected List<HomeEntity.ListCategoryInfoVoBean> getDataSource() {
        return typeList;
    }

    @Override
    protected void onBindViewHolder(CommonViewHolder holder, HomeEntity.ListCategoryInfoVoBean listCategoryInfoVoBean, int position) {
        final String shopName = listCategoryInfoVoBean.getCategory_name();
        String shopIcon = listCategoryInfoVoBean.getPicture();

        holder.setText(R.id.tv_type, shopName);
        ImageView ivIcon = (ImageView) holder.getView(R.id.iv_icon);
        Glide.with(context).load(shopIcon).apply(RequestOptions.bitmapTransform(new CircleCrop())).into(ivIcon);

        ivIcon.setOnClickListener(v -> homeFragment.onServiceTypeItemClick(shopName));
    }
}
 


下面说几句废话

在我能力尚弱的时候,我看了鸿洋的封装,能看懂,但是始终不明白,为啥我就想不出来应该这样封装。随着封装的东西多了,面向对象的思维深了,开始明白了。封装的思路是这样形成的:

基本上都是写了很多的重复的代码之后才意识到要封装的。

封装是循序渐进的,一点一点优化,可能今天优化了这个,明天优化了那个,随着时间流逝,封装也会趋于完美,所以封装是一个阶段性很强的操作。

最后发现要封装的地方,这里形成的思维就是,ViewHolder首先是可以复用的,这是写了许多ViewHolder后的出来的结论;

然后Adapter有些代码也是可以复用的,比如onCreateViewHolder里的大部分代码都是冗余的,只需要一个item布局id即可,然后数据源的数量一般也是固定的,而且从数据源中根据position拿到单个元素这个操作也是可以封装的,所以采用了泛型进行一个简化。

最后发现用返回一个方法的形式返回item布局id还是显得有些冗余,所以就采用了注解。

到这里,一个正常情况下的adapter就封装完毕了,只有两个方法,取得数据源,和绑定数据。

注意,这只是正常情况下的adapter,多item type的情况显然不适用,所以说封装是一步步的。只有产生了新的需求,代码才会冗余;只有编写了一定量的冗余的代码后,才会意识到要进行一个封装。封装不是一口气吃成一个胖子,当然你可以从一开始就把整个所有封装的可能都封装好。但是这样真的不会影响你工作吗?而且前期思考的再好,总会有纰漏,还不如一层一层,递进封装。分层思想,是编程思想中最为荟萃与闪光的一点。

还有一个注意点就是,注解只能封装正常的类型,任何的Object都是不支持的,不然这里会把数据源也封装进去,那就舒服了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值