关于动态添加RecyclerView的Item问题

1,608次阅读
没有评论

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

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

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

Adapter类封装:

public abstract class BaseAdapter extends RecyclerView.Adapter {
private List 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 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 {

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 extends BaseAdapter {

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动态添加,其它功能可自行拓展。

正文完
 0
评论(没有评论)