Amagi82 Amagi82 - 5 months ago 25
Android Question

How can I add child lists inside RecyclerView items efficiently, like in the Google Keep app?

I'm trying to create a

RecyclerView
with a variety of modules in a grid, some of which contain lists of child items. How do I add those child lists without causing stuttering when the user scrolls?

I've tried adding a
LinearLayout
to my
ViewHolder
, and inflating the child views manually in
onBindViewHolder
, as well as using nested RecyclerViews. Both have performance issues, and nested RecyclerViews have the added problem of wrap_content not playing nice.

Any suggestions for optimizing performance? Am I missing a better way?

@Override
public int getItemViewType(int position) {
return modules.get(position).getType().ordinal();
}

@Override
public ModuleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (types[viewType]) {
case LINEARLAYOUTSTATBLOCK:
return new ModuleLLBlockViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.module_block, parent, false));
case RECYCLERVIEWSTATBLOCK:
return new ModuleRVBlockViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.module_block, parent, false));
}
}

@Override
public void onBindViewHolder(ModuleViewHolder vh, final int position) {
switch (types[vh.getItemViewType()]) {
case LINEARLAYOUTSTATBLOCK:
bind((ModuleLLBlockViewHolder) vh, (StatBlockModule) modules.get(position));
break;
case RECYCLERVIEWSTATBLOCK:
bind((ModuleRVBlockViewHolder) vh, (StatBlockModule) modules.get(position));
break;
}
}

private void bind(ModuleLLBlockViewHolder vh, TitleTextBlockModule module) {
for (int i = 0; i < module.getStats().size(); i++) {
View v = LayoutInflater.from(vh.linearLayout.getContext()).inflate(R.layout.row, vh.linearLayout, true);
v.setId(i);
TextView tvCategory = (TextView) v.findViewById(R.id.tvCategory);
CustomView customView = (CustomView) v.findViewById(R.id.customView);
tvCategory.setText(stat.getCategory());
customView.setRating(stat.getRating());
}
}

private void bind(ModuleRVBlockViewHolder vh, StatBlockModule module) {
vh.childRecyclerView.setLayoutManager(new LinearLayoutManager(vh.itemView.getContext()));
vh.childRecyclerView.setAdapter(new ChildAdapter(module.getStats()));
}


Google Keep example

Answer

With Android Support Library 23.2, RecyclerView now obeys wrap_content, so it can be used inside a list item.

You should set android:nestedScrollingEnabled="false" on the inner RecyclerView(s) so scrolling is handled by the outer RecyclerView alone.

Comments