单个RecyclerView多布局实现求助:合并适配器遇对象引用问题
Hey there! Let's work through this RecyclerView multi-layout challenge step by step. You're on the right track merging adapters, but there are a few key issues in your current code that are blocking progress—plus we'll extend it to support 4 layouts easily.
First, Fix the Critical Issues in Your Current Code
Let's address the immediate errors and logical mistakes:
1. Correct getItemCount()
Right now you're returning 0, which means your RecyclerView will never show any items. Change it to return the size of your items list:
@Override public int getItemCount() { return items != null ? items.size() : 0; }
2. Fix onCreateViewHolder() Return Type
Your method declares it returns ChestViewHolder, but you're trying to return BicepsViewHolder for one view type. Update the return type to RecyclerView.ViewHolder (since both holders are subclasses of it):
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); if (viewType == ITEM_TYPE_S_B){ View view = layoutInflater.inflate(R.layout.segment_one, parent, false); return new BicepsViewHolder(view); } else { View view = layoutInflater.inflate(R.layout.segment_two, parent, false); return new ChestViewHolder(view); } }
3. Fix bind() Method Parameters
Your bind() methods are currently accepting MultiAdapter as a parameter, which doesn't make sense—they should accept your custom data objects (e.g., FirstObj and SecondObj). Update them like this:
public static class ChestViewHolder extends RecyclerView.ViewHolder{ TextView second_segment; public ChestViewHolder(View itemView) { super(itemView); second_segment = itemView.findViewById(R.id.segment_tuesday); } public void bind(FirstObj firstObj) { // Populate your TextView with data from firstObj second_segment.setText(firstObj.getSomeData()); } } public static class BicepsViewHolder extends RecyclerView.ViewHolder { TextView first_segment; public BicepsViewHolder(View itemView) { super(itemView); first_segment = itemView.findViewById(R.id.segment_monday); } public void bind(SecondObj secondObj) { // Populate your TextView with data from secondObj first_segment.setText(secondObj.getOtherData()); } }
4. Fix getItemViewType() Logic
You're checking if an item is an instance of MultiAdapter, which is your adapter class—not your data objects. Change this to check for your actual custom data types:
// First, define your constants properly (assign unique integers) private static final int ITEM_TYPE_C_T = 0; private static final int ITEM_TYPE_S_B = 1; @Override public int getItemViewType(int position) { Object item = items.get(position); if (item instanceof FirstObj) { return ITEM_TYPE_C_T; } else if (item instanceof SecondObj) { return ITEM_TYPE_S_B; } // Add a default case to avoid crashes throw new IllegalArgumentException("Unknown item type at position: " + position); }
Extend to Support 4 Layouts
Now that your 2-layout setup works, scaling to 4 is straightforward:
1. Add More Item Type Constants
private static final int ITEM_TYPE_C_T = 0; private static final int ITEM_TYPE_S_B = 1; private static final int ITEM_TYPE_TRICEPS = 2; // New type private static final int ITEM_TYPE_LEGS = 3; // New type
2. Create New ViewHolder Classes
Make a holder for each new layout, mirroring the pattern you used for the first two:
public static class TricepsViewHolder extends RecyclerView.ViewHolder{ TextView tricepsText; public TricepsViewHolder(View itemView) { super(itemView); tricepsText = itemView.findViewById(R.id.segment_wednesday); } public void bind(TricepsObj tricepsObj) { tricepsText.setText(tricepsObj.getTricepsData()); } } public static class LegsViewHolder extends RecyclerView.ViewHolder{ TextView legsText; public LegsViewHolder(View itemView) { super(itemView); legsText = itemView.findViewById(R.id.segment_thursday); } public void bind(LegsObj legsObj) { legsText.setText(legsObj.getLegsData()); } }
3. Update getItemViewType()
Add checks for your new data types:
@Override public int getItemViewType(int position) { Object item = items.get(position); if (item instanceof FirstObj) { return ITEM_TYPE_C_T; } else if (item instanceof SecondObj) { return ITEM_TYPE_S_B; } else if (item instanceof TricepsObj) { return ITEM_TYPE_TRICEPS; } else if (item instanceof LegsObj) { return ITEM_TYPE_LEGS; } throw new IllegalArgumentException("Unknown item type at position: " + position); }
4. Update onCreateViewHolder()
Add cases to inflate the new layouts and create the corresponding holders:
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); switch (viewType) { case ITEM_TYPE_S_B: View segmentOneView = layoutInflater.inflate(R.layout.segment_one, parent, false); return new BicepsViewHolder(segmentOneView); case ITEM_TYPE_C_T: View segmentTwoView = layoutInflater.inflate(R.layout.segment_two, parent, false); return new ChestViewHolder(segmentTwoView); case ITEM_TYPE_TRICEPS: View segmentThreeView = layoutInflater.inflate(R.layout.segment_three, parent, false); return new TricepsViewHolder(segmentThreeView); case ITEM_TYPE_LEGS: View segmentFourView = layoutInflater.inflate(R.layout.segment_four, parent, false); return new LegsViewHolder(segmentFourView); default: throw new IllegalArgumentException("Unknown view type: " + viewType); } }
5. Update onBindViewHolder()
Add cases to bind data to the new holders:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { Object item = items.get(position); if (holder instanceof ChestViewHolder) { ((ChestViewHolder) holder).bind((FirstObj) item); } else if (holder instanceof BicepsViewHolder) { ((BicepsViewHolder) holder).bind((SecondObj) item); } else if (holder instanceof TricepsViewHolder) { ((TricepsViewHolder) holder).bind((TricepsObj) item); } else if (holder instanceof LegsViewHolder) { ((LegsViewHolder) holder).bind((LegsObj) item); } else { throw new IllegalArgumentException("Unknown view holder type"); } }
Bonus: Optional Optimization
If you want to make your code cleaner, you could create a base data class or interface that all your custom objects implement, then use that in your items list instead of Object. But for simple use cases, the above approach works perfectly.
内容的提问来源于stack exchange,提问作者Kristian

