'Nested RecyclerView load second item with lag
I'm trying to make Recyclerview like Shareit app. It uses sticky header and something like Cardview. I searched and found somethings for implementing sticky header with itemdecoration and it's okay. But for Cardview part, I tried to make nested Recyclerview but performance was so bad, Because using two vertical Recyclerview is not good at all. Is there any better way to achieve this?
The problem with performance is for when i scroll down. It makes lag on creating second item in parent Recyclerview.
AppheaderAdapter:
@Override
public AppHeaderAdapter.HeaderHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_media_header, parent, false);
HeaderHolder headerHolder = new HeaderHolder(view);
return headerHolder;
}
class HeaderHolder extends RecyclerView.ViewHolder { //story
final ImageView arrow;
final TextView tarikh;
final TextView tedad;
final CheckBox tick;
final RecyclerView item_recyc;
HeaderHolder(View itemView) {
super(itemView);
arrow = itemView.findViewById(R.id.header_arrow);
tarikh = itemView.findViewById(R.id.header_tarikh);
tedad = itemView.findViewById(R.id.header_tedad);
tick = itemView.findViewById(R.id.header_tick);
item_recyc = itemView.findViewById(R.id.header_recyc);
}
}
@Override
public void onBindViewHolder(@NonNull AppHeaderAdapter.HeaderHolder headerHolder, int position) {
final AppHeader appHeader = appHeaders.get(position);
...
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, span);
gridLayoutManager.setRecycleChildrenOnDetach(true);
headerHolder.item_recyc.setLayoutManager(gridLayoutManager);
headerHolder.item_recyc.setNestedScrollingEnabled(false);
AppItemAdapter adapter = new AppItemAdapter(context, appHeader.getAppList(), fr_parent, width);
headerHolder.item_recyc.swapAdapter(adapter, true);
...
}
item_media_header.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/so_round_so_white"
app:cardCornerRadius="10dp"
app:cardElevation="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/header_arrow"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="8dp"
android:src="@drawable/header_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/header_tarikh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/fragment_file"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/header_arrow"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/header_tedad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:textColor="#AAAAAA"
android:textSize="@dimen/fragment_file"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/header_tarikh"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="@+id/header_tick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:button="@null"
android:clickable="false"
android:drawableRight="@drawable/file_checkbox"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/header_recyc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
EDIT 1:
I find that just first Cardview is loaded and second one is not loaded until I scroll to end of first one and then load second CardView item and it lags because of second RecyclerView.
I found that Shareit use previous created adapter and just change its internal datalist, So i do that, but still has lag on second item.
Edite 2:
I use one time created adapter on all RecyclerView but still has lag.
Edit 3:
It's a known bug that innerRecyclerView load all items at first and that cause my lag too. because inner Recyclerview is inside NestedScrollView (RV) and it loads all content.Using constant height doesn't work, But I'll update question if I find something better.
Solution 1:[1]
You can achieve this with ConstraintLayout and Flow.
EDIT: Sorry, I just realised I wrote everything in Kotlin. If you cannot understand something I can try to translate it to Java.
xml:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
...>
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow"
app:flow_wrapMode="aligned"
app:flow_horizontalStyle="spread_inside"
app:flow_maxElementsWrap="4"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Adding of items:
val constraintLayout = itemView.findViewById(R.id.constraintLayout)
val flow = itemView.findViewById(R.id.flow)
val items // items given to the viewHolder to display
val layoutInflater = LayoutInflater.from(context)
items.forEach { item ->
val view = // create item view, e.g. DataBinding, ...
view.id = ViewCompat.generateViewId()
constraintLayout.addView(root)
flow.addView(root)
}
}
// if there are less than 4 items you have to add invisible dummy items. Otherwise, the alignment will look different for these ViewHolders
if(items.size>=4) return
for (i in 0..(4-items.size)) {
val view = // create dummy view
view.id = ViewCompat.generateViewId()
constraintLayout.addView(root)
flow.addView(root)
}
Solution 2:[2]
So far, Using vertical RV inside vertical RV has bug. Because of inner RV make long height and outer RV has no idea of this, So it create just first Item, but all items in inner RV. using all solution on Stack O.F. had no effect!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | forootan |

