Nested lag recylerview while the first few scrolls and then scrolls smoothly?

I am using a nested RecyclerView. The tool inside the vertical RecyclerView I have several types of horizontal recycler

I connect the adapter to horizontal recylerviews inside the onBindViewHolder method of the parent RecyclerView as follows.

@Override public void onBindViewHolder(final MainViewHolder holder, final int position) { switch (holder.getItemViewType()) { case TYPE_PRODUCT: ((ListHolderProduct) holder).itemTitle.setText(browseCategoryHomePageItems.get(position).displayName.toUpperCase()); ((ListHolderProduct) holder).recyclerView.setAdapter(new CarouselProductsRecyclerAdapter(context , browseCategoryHomePageItems.get(position).products , R.layout.activity_categoryhome_products_grid_item , nestedRecyclerItemClickedListener , position)); break; case TYPE_DEAL: ((ListHolderDeal) holder).itemTitle.setText(browseCategoryHomePageItems.get(position).displayName.toUpperCase()); ((ListHolderDeal) holder).recyclerView.setAdapter(new CarouselDealsRecyclerAdapter(context , browseCategoryHomePageItems.get(position).dealItems , R.layout.activity_categoryhome_deals_grid_item , nestedRecyclerItemClickedListener , position)); break; //few more types like this } } 

Now, when I scroll the page, it lags a little, since I connect the adapter to the horizontal RecyclerView on the OnBindViewHolder

And there may be N Number of TYPE_PRODUCT or any types of horizontal lists. This means that there can be more than one horizontal list of the same type.

Any idea how I can optimize this thing and improve scroll speed.

This is a lag since the setAdapter is called every time for the list earlier.

Update on this issue I am expanding the LinearLayoutManager, and in this I am setting the extraLayout space, which fixed my problem, but I do not know if this is the right way or not. I set the extra space as shown below.

  layoutManager.setExtraLayoutSpace(2 * this.getResources().getDisplayMetrics().heightPixels); 

and then the custom layout manager class

 public class PreCachingLayoutManager extends LinearLayoutManager { private static final int DEFAULT_EXTRA_LAYOUT_SPACE = 600; private int extraLayoutSpace = -1; private Context context; public PreCachingLayoutManager(Context context) { super(context); this.context = context; } public PreCachingLayoutManager(Context context, int extraLayoutSpace) { super(context); this.context = context; this.extraLayoutSpace = extraLayoutSpace; } public PreCachingLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); this.context = context; } public void setExtraLayoutSpace(int extraLayoutSpace) { this.extraLayoutSpace = extraLayoutSpace; } @Override protected int getExtraLayoutSpace(RecyclerView.State state) { if (extraLayoutSpace > 0) { return extraLayoutSpace; } return DEFAULT_EXTRA_LAYOUT_SPACE; } 

}

+7
source share
4 answers

Do not create a horizontal adapter every time in onBindViewHolder , instead of creating an appropriate adapter in each ViewHolder class (ListHolderDeal, ListHolderProduct). Then, in the onBindViewHolder vertical Recyclerview simply replace the data of this adapter, and if the horizontal RecyclerView does not have an adapter, install it using the view holder adapter. If so, replace the data set of this adapter and call notifyDataSetChange . With this approach, you can implicitly use the adapter pool so that the garbage collector can bother you less.

I hope this helps.

+4
source

I had the same scrolling issue due to loading images while scrolling. Therefore, you need to use the Picasso library to load images and do pause_tag if you use onScrollListener.

In onBindViewHolder Picasso.with (context) .load (foodData.getRecipe_resize_image_url ()) .resize (width, height) .placeholder (R.drawable.empty_image) .tag ("resume_tag") .into (mainViewHolder.food_picture);

In onScrollListener

 @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); final Picasso picasso = Picasso.with(context); if (newState == RecyclerView.SCROLL_STATE_IDLE) { picasso.resumeTag("resume_tag"); } else { picasso.pauseTag("resume_tag"); } } 
+1
source

Please check if the getItemViewType(int position) method is canceled if you do not override this method and tell how many types of views your recyclerview will process, from the above code there are two types of views for TYPE_PRODUCT and the other for TYPE_DEAL .

This particular method, if it overrides and returns the correct number of types, prevents unwanted layout inflation for an already accessible typed view (in the recycler cache), which dramatically increases performance.

For example, to implement a multiple typed recyclerview, refer to this question .

Link: http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#getItemViewType%28int%29

Hope this helps !!! Please let me know if you have a problem with this. Thanks.

0
source

RecyclerView uses the view pool to prevent recreating the views, which improves performance, but when we use the RecyclerView inside the RecyclerView internal RecyclerView has its own view pool, so the external RecyclerView scrolls each view of the internal RecyclerView every time because it has a separate view pool.

Thus, to use the same view, we need to add this code to the external RecyclerView adapter:

 public OuterRecyclerViewAdapter(List<Item> items) { //Constructor stuff viewPool = new RecyclerView.RecycledViewPool(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //Create viewHolder etc holder.innerRecyclerView.setRecycledViewPool(viewPool); } 

I found this information from this useful article.

0
source

All Articles