Java中如何复用单个RecyclerView Adapter适配多种布局?
复用现有RecyclerView Adapter适配多种布局的方案
当然不需要新建Adapter啦!我们可以利用RecyclerView自带的**多视图类型(Multiple View Types)**机制,轻松改造你现有的BookRecyclerViewAdapter,让它同时适配你的可展开CardView和另一种布局。下面我结合你的代码一步步说明具体修改步骤:
步骤1:定义视图类型常量
首先在BookRecyclerViewAdapter里添加两个常量,用来区分两种不同的布局:
public class BookRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { // 视图类型常量:可展开CardView布局 private static final int VIEW_TYPE_EXPANDABLE_CARD = 0; // 视图类型常量:新的另一种布局 private static final int VIEW_TYPE_OTHER_LAYOUT = 1; private ArrayList<Book> books = new ArrayList<>(); private Context context; // 保存当前要使用的视图类型 private int currentViewType; // 修改构造方法,传入当前要使用的视图类型 public BookRecyclerViewAdapter(Context context, int currentViewType) { this.context = context; this.currentViewType = currentViewType; } // ... 其他原有代码 }
步骤2:重写getItemViewType方法
这个方法告诉RecyclerView每个位置对应的视图类型,因为你是在不同Activity中使用整个列表的同一种布局,所以直接返回我们传入的currentViewType即可:
@Override public int getItemViewType(int position) { return currentViewType; }
步骤3:修改ViewHolder结构
因为现在有两种布局,需要分别创建对应的ViewHolder。保留你原来的可展开CardView逻辑,重命名ViewHolder让代码更清晰,再新增一个对应新布局的ViewHolder:
// 原来的可展开CardView对应的ViewHolder,重命名更清晰 public class ExpandableCardViewHolder extends RecyclerView.ViewHolder { private CardView parent; private ImageView imgBook; private TextView txtName; private ImageView downArrow, upArrow; private RelativeLayout expanded, collapsed; private TextView txtAuthor, txtDesc; public ExpandableCardViewHolder(@NonNull View itemView) { super(itemView); parent = itemView.findViewById(R.id.parent); // 注意:这里原来的引号要去掉,直接用R.id.xxx imgBook = itemView.findViewById(R.id.imgBook); txtName = itemView.findViewById(R.id.txtBookName); downArrow = itemView.findViewById(R.id.btnDownArrow); upArrow = itemView.findViewById(R.id.btnUpArrow); expanded = itemView.findViewById(R.id.expandedRellayout); collapsed = itemView.findViewById(R.id.collapsedRelLayout); txtAuthor = itemView.findViewById(R.id.txtAuthor); txtDesc = itemView.findViewById(R.id.txtShortDesc); // 原有点击事件逻辑保留 downArrow.setOnClickListener(v -> { Book book = books.get(getAdapterPosition()); book.setExpanded(!book.isExpanded()); notifyItemChanged(getAdapterPosition()); }); upArrow.setOnClickListener(v -> { Book book = books.get(getAdapterPosition()); book.setExpanded(!book.isExpanded()); notifyItemChanged(getAdapterPosition()); }); } } // 新布局对应的ViewHolder public class OtherLayoutViewHolder extends RecyclerView.ViewHolder { // 根据你的新布局定义控件,示例如下: private TextView tvBookTitle; private ImageView ivCover; public OtherLayoutViewHolder(@NonNull View itemView) { super(itemView); tvBookTitle = itemView.findViewById(R.id.tv_book_title); ivCover = itemView.findViewById(R.id.iv_cover); // 新布局的点击事件逻辑,比如跳转到详情页 itemView.setOnClickListener(v -> { Book book = books.get(getAdapterPosition()); Intent intent = new Intent(context, BookActivity.class); intent.putExtra("BOOK_ID_KEY", book.getId()); context.startActivity(intent); }); } }
步骤4:修改onCreateViewHolder方法
根据不同的视图类型加载对应的布局文件,并返回对应的ViewHolder:
@NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); if (viewType == VIEW_TYPE_EXPANDABLE_CARD) { View view = inflater.inflate(R.layout.list_item_book, parent, false); // 去掉原来的引号 return new ExpandableCardViewHolder(view); } else { // 加载你的新布局文件 View view = inflater.inflate(R.layout.your_new_book_layout, parent, false); return new OtherLayoutViewHolder(view); } }
步骤5:修改onBindViewHolder方法
根据不同的ViewHolder类型,绑定对应的数据和逻辑:
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { Book book = books.get(position); if (holder instanceof ExpandableCardViewHolder) { // 原来的可展开CardView绑定逻辑保留 ExpandableCardViewHolder cardHolder = (ExpandableCardViewHolder) holder; cardHolder.txtName.setText(book.getName()); cardHolder.txtAuthor.setText(book.getAuthor()); cardHolder.txtDesc.setText(book.getShortDesc()); Glide.with(context) .asBitmap() .load(book.getImgUrl()) .into(cardHolder.imgBook); cardHolder.parent.setOnClickListener(v -> { Intent intent = new Intent(context, BookActivity.class); intent.putExtra("BOOK_ID_KEY", book.getId()); context.startActivity(intent); }); if (book.isExpanded()) { TransitionManager.beginDelayedTransition(cardHolder.parent); cardHolder.expanded.setVisibility(View.VISIBLE); cardHolder.downArrow.setVisibility(View.GONE); } else { TransitionManager.beginDelayedTransition(cardHolder.parent); cardHolder.expanded.setVisibility(View.GONE); cardHolder.downArrow.setVisibility(View.VISIBLE); } } else if (holder instanceof OtherLayoutViewHolder) { // 新布局的绑定逻辑 OtherLayoutViewHolder otherHolder = (OtherLayoutViewHolder) holder; otherHolder.tvBookTitle.setText(book.getName()); Glide.with(context) .load(book.getImgUrl()) .into(otherHolder.ivCover); // 其他新布局需要的绑定操作 } }
如何在不同Activity中使用
- 在原来使用可展开CardView的Activity中:
BookRecyclerViewAdapter adapter = new BookRecyclerViewAdapter(this, BookRecyclerViewAdapter.VIEW_TYPE_EXPANDABLE_CARD); // 设置数据等操作 recyclerView.setAdapter(adapter);
- 在新的Activity中使用另一种布局:
BookRecyclerViewAdapter adapter = new BookRecyclerViewAdapter(this, BookRecyclerViewAdapter.VIEW_TYPE_OTHER_LAYOUT); // 设置数据等操作 recyclerView.setAdapter(adapter);
这样就完美复用了同一个Adapter,不需要额外新建啦!另外提个小细节:你原来代码里findViewById和inflate中的"R.id.xxx"是错误的,要去掉引号直接用R.id.xxx哦。
内容的提问来源于stack exchange,提问作者user14498195
相关产品推荐
相关产品推荐

