一种多种样式RecylerView的adapter低耦合封装方式

项目中用到的最多的元素就是列表,在android中目前最流行了的当属RecylerView了。项目中也涉及到很多RecylerView替换Listview的场景。看过比较多对adapter封装的文章,总有些不太简洁。所以本文将介绍自己封装的高度解耦Adapter和viewholder。帮你快速高效生成一个万能列表。

理念

  1. 构造一个通用的Adapter,避免一个列表一个适配器,避免增加(viewType)item列表就要对Adapter进行修改。
  2. 将每个Item抽象成独立组件,每个独立组件可在使用适配器前任意位置注册,完全数据驱动样式
  3. 支持多数据model和多样式一一对应
  4. 高内聚低耦合

思路

  1. 抽象数据model,每个数据model实现抽象接口IRvSmartCell。
  2. 封装Adapter的getItemViewType,实现model中type和viewType对应
  3. 封装万能ViewHolder,通过接口桥接代理ViewHolder的绑定和解绑
  4. 封装Adapter的onCreateViewHolder和onBindViewHolder
  5. 样式仓库,注册列表cell的实现

实现

  1. model接口的定义
/**
 * 万能适配器的model接口
 */
public interface IRvSmartCell {
    /**
     * 
     * @return 返回唯一的itemType
     */
    String getType();
}

/**
 * 一种model的默认实现
 */
public class RvSmartBaseCell implements IRvSmartCell {
    protected String itemType;

    public RvSmartBaseCell(String itemType) {
        this.itemType = itemType;
    }

    @Override
    public String getType() {
        return itemType;
    }
}
  1. 封装Adapter的getItemViewType
@Override
public int getItemViewType(int position) {
    T data = mDataList.get(position);
    if (data == null)
        return -1;
    // we should use getType()
    String typeKey = data.getType();
    if (!mStrKeys.containsKey(typeKey)) {
        int newType = mTypeId.getAndIncrement();
        mStrKeys.put(typeKey, newType);
        mId2Types.put(newType, data.getType());
    }
    return mStrKeys.get(typeKey).intValue();

}
  1. 封装万能ViewHolder
public class RvSmartHolder<T extends IRvSmartCell, V extends View> extends RecyclerView.ViewHolder {

    public IRvSmartBinder<T, V> controller;

    public V itemView;

    public T data;

    public RvSmartHolder(@NonNull V itemView, @NonNull IRvSmartBinder<T, V> binder) {
        super(itemView);
        this.itemView = itemView;
        this.controller = binder;
    }

    public void bindHolder(T data){
        controller.mountView(data, itemView);
        this.data = data;
    }


    public void unBindHolder(){
        if (data != null){
            controller.unmountView(data, itemView);
        }
    }

}

  1. 封装Adapter的onCreateViewHolder和onBindViewHolder
    @NonNull
    @Override
    public RvSmartHolder<T, ? extends View> onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        String type = getCellTypeFromItemType(i);
        try {
            Class<? extends IRvSmartBinder> clz = IRvCellWarehouse.getInstance().getHolder(type);
            IRvSmartBinder holder = clz.newInstance();
            return createViewHolder(holder, viewGroup.getContext(), viewGroup);
        }catch (Throwable error){

        }
        return null;
    }

    public <V extends View> RvSmartHolder<T, V> createViewHolder(
            @NonNull final IRvSmartBinder<T, V> binder, @NonNull final Context context, final ViewGroup parent){
        V view = binder.createView(context, parent);
        return new RvSmartHolder<>(view, binder);
    }


    @Override
    public void onBindViewHolder(@NonNull RvSmartHolder<T, ? extends View> rvSmartHolder, int i) {
        T data = mDataList.get(i);
        rvSmartHolder.bindHolder(data);
    }
  1. 样式仓库(单例)
public class IRvCellWarehouse {
    private HashMap<String, Class<? extends IRvSmartBinder<? extends IRvSmartCell, ? extends View>>> mHolderCenter = new HashMap<>();

    private IRvCellWarehouse(){

    }

    public static IRvCellWarehouse getInstance(){
        return Holder.instance;
    }
    private static class Holder {
        private static final IRvCellWarehouse instance = new IRvCellWarehouse();
    }

    public void register(String type, Class<? extends IRvSmartBinder<? extends IRvSmartCell, ? extends View>> clz){
        mHolderCenter.put(type, clz);
    }

    public Class<? extends IRvSmartBinder<? extends IRvSmartCell, ? extends View>> getHolder(String type){
        return mHolderCenter.get(type);
    }

}
  1. 桥接接口定义
/**
 * holder的桥接接口定义相关方法模板
 * @param <T>
 * @param <V>
 */
public interface IRvSmartBinder<T extends IRvSmartCell, V extends View> {

    @NonNull
    V createView(Context context, ViewGroup parent);

    void mountView(@NonNull T data, @NonNull V view);

    void unmountView(@NonNull T data, @NonNull V view);

}

使用

首先注册实现了桥接接口的binder ,这里在app启动时候进行了注册两种itemType 1和2

public class AppApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        IRvCellWarehouse.getInstance().register("0", AdapterCell1.class);
        IRvCellWarehouse.getInstance().register("1", AdapterCell2.class);
    }
}

这里为了方便简单生成了两种模型通过for循环生成了50条数据

recyclerView.setLayoutManager(new LinearLayoutManager(this));

        for (int i = 0; i < 50; i ++){
            if (i % 2 == 0) {
                AdpModel model = new AdpModel(i % 2 +"");
                model.i = i + "";
                list.add(model);
            }else if (i % 2 == 1){
                AdpModel2 model = new AdpModel2(i % 2 + "");
                model.i = i + "";
                model.name = "pan";
                list.add(model);
            }

        }

        RVSmartAdapter<IRvSmartCell> smartAdapter = new RVSmartAdapter<>();
        smartAdapter.setData(list);
        recyclerView.setAdapter(smartAdapter);
public class AdpModel extends RvSmartBaseCell {

    public String i;
    public AdpModel(String itemType) {
        super(itemType);
    }
}

效果

简单写了两种样式
样式一:textview
样式二:button
在这里插入图片描述

源码地址

包结构
在这里插入图片描述

源码地址github

发布了26 篇原创文章 · 获赞 0 · 访问量 1137

猜你喜欢

转载自blog.csdn.net/Plx0303sunny/article/details/102476068