Advanced RecyclerView Flashcards
Where is the best place to listen for / handle recyclerView item clicks?
Listen - ViewHolder (represents just one list item)
Handle - ViewModel (has the data and logic available)
List the steps for implementing a ViewHolder ClickListener
Create a Listener class Add a ^variable^ representing the listener to the ^data^ in the item's layout xml Add onClick property to item xml ConstraintLayout, referencing a data binding lambda (eg "@{( ) -^ clickListener.onClick(sleep)}" Pass the Listener down through the Adapter constructor to set binding.clickListener = clickListener in ViewHolder.bind() Add functionality handling the click by instantiating a Listener in the Adapter's constructor in Fragment.onCreateView()
What is the Codelabs pattern for handling RecyclerView Clicks?
- clickListener instantiated in Adapter’s constructor in Fragment.onCreateView( ) passes item id to a viewModel function
- viewModel function uses item id to set a MutableLiveData.value
- functionality handling the click is set in the MutableLiveData’s observer function in Fragment.onCreateView( )
How do you define a Listener for ViewHolder clicks?
class MyItemListener(val clickListener: (itemId:Long) -^ Unit){ fun onClick(entity: Entity) = clickListener(entity.entityId)
List the steps for adding a header item to the RecyclerView
- Create a sealed class containing subclasses representing the different types of item and an object representing the header item
- Add a layout xml for the header item
- Create a new ViewHolder class for the Header item
- Update the Adapter (see another card)
- Update the DiffCallback class (replace item type with sealed class type)
List the steps for updating the adapter when adding a header item to the RecyclerView
a) assign constant values for different view types eg private val ITEM_VIEW_TYPE_HEADER = 0 b) override getItemViewType - use a return when( ) to return the correct int constant depending on the item returned by getItem(position) c) replace references to item type in class / function definitions with reference to parent sealed class d) replace references to ViewHolder type with RecyclerView.ViewHolder e) use a when in all Adapter functions to perform different logic depending on the the item type f) create a new function to wrap Adapter.submitList( ) so it always includes a header.
Define the function for wrapping Adapter.submitList so it always returns the header but only adds items of a list if the list is not null.
fun addHeaderAndSubmitList(list: List?) { val items = when (list) { null -> listOf(DataItem.Header) else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) } } submitList(items) }
When working with large lists, how do you ensure that Adapter work does not block the main thread?
Wrap work preparatory to submitList( ) (mapping the list to RecyclerView items, adding the header) in a CoroutineScope before calling submitList( ) on the main thread
What is needed to display one item across several spans?
manager.spansizeLookup = object : GridLayoutManager.SpanSizeLookup( ){
override fun getSpanSize(position: Int) = when (position) {
(position of item requiring X spans) -> X
else -> 1
}
}