Closed marwanf1 closed 7 years ago
My guess is this is probably unrelated to epoxy - but RecyclerView itself. They made recent updates to it in the support library to address an issue that sounds like what you're describing
https://developer.android.com/topic/libraries/support-library/revisions.html#25-1-0
Clients of nested RecyclerView widgets (for example, vertical scrolling list of horizontal scrolling lists) can get significant performance benefits by hinting the inner RecyclerView widgets’ layout managers how many items to prepare before being scrolled on screen. Call LinearLayoutManager.setInitialPrefetchItemCount(N), where N is the number of views visible per inner item...
This is a bit unrelated to Epoxy. I've spent a lot of time experimenting to find the best ways to deal with carousels though for our own app. The main trick is to make sure that you are properly recycling views when changing the carousel adapter. I'll try to post some examples soon.
@kevinthecity Thanks that's a really helpful method.
@elihart I know it's not an issue in Epoxy but the main reason I opened this issue is to maybe add a carousel example to the sample app. Most applications are using carousels and it would be helpful to see how to apply that in Epoxy. Looking forward to the examples thanks.
@marwanf1 Here is a carousel model very similar to what we use
public class CarouselEpoxyModel<A extends EpoxyAdapter> extends AirEpoxyModel<RecyclerView> {
@EpoxyAttribute A adapter;
@EpoxyAttribute RecycledViewPool recycledViewPool;
@LayoutRes
public int getDefaultLayout() {
return R.layout.view_holder_carousel;
}
@Override
public void bind(RecyclerView carousel) {
super.bind(carousel);
// If there are multiple carousels showing the same item types, you can benefit by having a shared view pool between those carousels
// so new views aren't created for each new carousel.
if (recycledViewPool != null) {
carousel.setRecycledViewPool(recycledViewPool);
}
// Carousels are generally fixed height. Using fixed size is a small optimization we can make in that case.
carousel.setHasFixedSize(true);
// Use swapAdapter instead of setAdapter, with 'removeAndRecycleExistingViews=false', so that the existing views in the carousel are
// reused. This only makes sense if the old adapter and new adapter share items of the same type, which is usually the case.
//
// Another benefit is that this will show change animations for differences between the old adapter and new adapter.
carousel.swapAdapter(adapter, false);
}
@Override
public void unbind(RecyclerView carousel) {
super.unbind(carousel);
// We again use swapAdapter instead of setAdapter so that the view pool is not cleared. 'removeAndRecycleExistingViews=true' is used
// since the carousel is going off screen and these views can now be recycled to be used in another carousel (assuming you have a shared view pool)
carousel.swapAdapter(null, true);
}
}
The key is using swapAdapter
instead of setAdapter
so that new views don't have to be created on every bind.
The shared view pool is another nice optimization if you have multiple recyclerviews in the same activity. You may want to look at https://github.com/airbnb/epoxy/issues/97 and use setRecycleChildrenOnDetach
so that if you leave a fragment and come back the views are properly recycled.
I'd like to add a more complete example to the sample app later on when I have time, but I think this will help you for now. Let me know if it works and if you have any more questions.
@elihart thank you so much its perfect and working smoothly.
Great! I'm also interested in experimenting with LinearLayoutManager.setInitialPrefetchItemCount(N)
inside the carousel model, but haven't gotten to that yet.
I'd like to add this code to the sample app sometime in the new few weeks. Or maybe someone else can contribute a PR :)
Can you please provide a sample for working with carousels? For example, a horizontal RecyclerView inside the vertical RecyclerView. The issue I'm facing is when data is binded to the horizontal view it becomes a bit sluggish on binding.
Thank you