关于动态添加RecyclerView的Item问题

    最近遇到一个需求:会话列表页面需要能动态添加一个可高度定制的Item。小小总结下自己的实现方式。

    一般情况下,在RecyclerView中我们引进不同的Item类型,都是提前确定好的,那如果遇到不确定类型的Item,如何处理?

那么就需要可以动态添加,灵活抽插,才是王道。

Adapter类封装:

public abstract class BaseAdapter<D extends Data> extends RecyclerView.Adapter<BaseHolder> {
    private List<D> mList;
    private OnRecyclerViewItemClickListener clickListener;
    private OnRecyclerViewItemLongClickListener longClickListener;
    
     public BaseAdapter(List<D> list) {
        this.mList = list;
    }

     @Override
    public int getItemViewType(int position) {
        return mList == null ? 0 : mList.get(position).getType();
    }    

      @NonNull
    @Override
    public BaseHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        BaseHolder baseHolder = null;
            /*以下调用带参的构造函数*/
            Constructor constructor = null;
            try {
                constructor = getViewHolderClass(viewType).getDeclaredConstructor(new Class[]{View.class});
                constructor.setAccessible(true);
                baseHolder = (BaseHolder) constructor.newInstance(getItemView(parent, viewType));
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        return baseHolder;
    }

     protected View getItemView(@NonNull ViewGroup parent, int viewType) {
        View view = null;
        view = LayoutInflater.from(parent.getContext()).inflate(getLayoutRes(viewType), parent, false);
        return view;
    }

    protected abstract @LayoutRes int getLayoutRes(int viewType);

    protected abstract Class<? extends BaseHolder> getViewHolderClass(int viewType);

    @Override
    public void onBindViewHolder(@NonNull BaseHolder holder, final int position) {
        holder.bindData(mList.get(position));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (clickListener != null) {
                    clickListener.onClick(v, position);
                }
            }
        });

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (longClickListener != null) {
                    longClickListener.onLongClick(v, position);
                    return true;
                } else
                    return false;
            }
        });

    }

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

    public void addOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener clickListener) {
        this.clickListener = clickListener;
    }

    public void addOnRecyclerViewItemLongClickListener(OnRecyclerViewItemLongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }

    public D getItemData(int position) {
        return mList == null ? null : mList.get(position);
    }

 }

BaseHolder

public abstract class BaseHolder<D extends Data> extends RecyclerView.ViewHolder {



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


    protected abstract void bindData(@NonNull D data);

}

Data是一个简单接口仅用于区分Item类型(列表中数据对象需实现)

public interface Data {

    int getType();

}

以上是RecyclerView使用Adapter的基础封装,正常使用直接继承即可,如:

public class TestAdapter extends BaseAdapter<User> {


    public TestAdapter(List<User> list) {
        super(list);
    }

    @Override
    protected int getLayoutRes(int viewType) {
        return R.layout.user_item_layout;
    }

    @Override
    protected Class<? extends BaseHolder> getViewHolderClass(int viewType) {
        switch (viewType){
            case 1:
                return UserHolder.class;
            case 2:
                return UserTwoHolder.class;
        }
        return UserHolder.class;
    }
}

简单的多类型直接使用即可。


下面动态添加,继承上面的BaseAdapter,如下:

public class SuperBaseAdapter<D extends Data> extends BaseAdapter<D> {


    public SuperBaseAdapter(List<D> list) {
        super(list);
    }

    @Override
    protected int getLayoutRes(int viewType) {
        return ItemUtils.getIntance().getLayoutRes(viewType);
    }

    @Override
    protected Class<? extends BaseHolder> getViewHolderClass(int viewType) {
        return ItemUtils.getIntance().getViewHolderClass(viewType);
    }

}

其中动态添加主要使用ItemUtils来处理:

public class ItemUtils {

    private static ItemUtils itemUtils;
    private SparseArray<Class<? extends BaseHolder>> sparseArrayItems;
    private SparseIntArray sparseArrayLayoutRes;

     private ItemUtils(){
        sparseArrayItems = new SparseArray<>();
        sparseArrayLayoutRes = new SparseIntArray();
    }

    public static ItemUtils getIntance(){
        if (itemUtils == null){
            synchronized (ItemUtils.class){
                if (itemUtils == null){
                    itemUtils = new ItemUtils();
                }
            }
        }
        return itemUtils;
    }

    public void addViewHolderItem(int viewType, @LayoutRes int layoutRes, Class<? extends BaseHolder> c){
        sparseArrayLayoutRes.put(viewType,layoutRes);
        sparseArrayItems.put(viewType,c);
    }

    protected int getLayoutRes(int viewType) {
        return sparseArrayLayoutRes.get(viewType);
    }

    protected Class<? extends BaseHolder> getViewHolderClass(int viewType) {
        return sparseArrayItems.get(viewType);
    }
}

具体例子:

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;

    private List<User> mList = new ArrayList<>();

//    private TestAdapter adapter;
    private TestSuperAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        recyclerView = findViewById(R.id.recycler_view);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));

//        adapter = new TestAdapter(mList);

        ItemUtils.getIntance().addViewHolderItem(1, R.layout.user_item_layout, UserHolder.class);
        ItemUtils.getIntance().addViewHolderItem(2, R.layout.user_item_layout, UserTwoHolder.class);
        adapter = new TestSuperAdapter(mList);


        recyclerView.setAdapter(adapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mList.clear();
        for (int i = 0; i < 20; i++) {
            User user = new User();
            if (i % 2 == 0) {
                user.setType(2);
            } else
                user.setType(1);
            user.setName("skwen" + (Math.random() * 30));
            user.setAge((int) (Math.random() * 30));
            mList.add(user);
        }
        adapter.notifyDataSetChanged();
    }


}

其中TestSuperAdapter知识继承了SuperBaseAdapter,未做任何处理。


整体就是使用ItemUtils类动态添加相应类型的Item即可。

ItemUtils的add方法,参数说明一下,

1 viewholder类型或者数据中携带的类型(不同数据不同viewHolder)

2 对应viewholder的布局文件id

3 viewholder的类

基本上简单的实现的RecyclerView的Item动态添加,其它功能可自行拓展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值