You should never use Option 1 if you want to display long lists in RecyclerView
. Placing RecyclerView
in NestedScrollView
will force RecyclerView to create all the items at once. You will lose recycling and your app will probably freeze in attempt to create all ViewHolders. It will also eat up a lot of memory. read more
Option 2 was the main way to implement lists with different layout types in it. But it makes the part of creating a list more complex. It would at least not work with Paging library 2.
Luckily, we now have a better alternative.
Starting with RecyclerView
version 1.2.0-alpha02 there is a new tool that can be used to easily create complex lists with different items in them. It is called ConcatAdapter
. You can read more about it in a great article by Florina Muntenescu on Medium.
As of 5/10/20, latest version of library is 1.2.0-alpha06. Despite library is still in alpha version, ConcatAdapter
is a great tool and I have been using it since it was first introduced. I never run into any problems so far. It works great and everything is pretty stable.
From my experience, I would say that this is probably the new best practice for adding headers and footers (and mixed type lists) in RecyclerView
.
ConcatAdapter
is also used in Paging library version 3. In this codelab they add header and footer to adapter natively.
binding.list.adapter = adapter.withLoadStateHeaderAndFooter(
header = ReposLoadStateAdapter { adapter.retry() },
footer = ReposLoadStateAdapter { adapter.retry() }
)
And adapter extends PagingDataAdapter
.
And if you go to the source code you will see that withLoadStateHeaderAndFoote
uses ConcatAdapter
under the hood.
/**
* Create a [ConcatAdapter] with the provided [LoadStateAdapter]s displaying the
* [LoadType.PREPEND] and [LoadType.APPEND] [LoadState]s as list items at the start and end
* respectively.
*
* @see LoadStateAdapter
* @see withLoadStateHeader
* @see withLoadStateFooter
*/
fun withLoadStateHeaderAndFooter(
header: LoadStateAdapter<*>,
footer: LoadStateAdapter<*>
): ConcatAdapter {
addLoadStateListener { loadStates ->
header.loadState = loadStates.prepend
footer.loadState = loadStates.append
}
return ConcatAdapter(header, this, footer)
}
All of these shows that ConcatAdapter
is starting to be heavily used and proves to be the best solution for multi-type lists.