Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RecyclerViews - Developer's Deep Dive

Divya Jain
September 27, 2021
160

RecyclerViews - Developer's Deep Dive

Presented this talk at Chicago Roboto '21 for a deep dive into the world of Recyclerviews.

Divya Jain

September 27, 2021
Tweet

Transcript

  1. Legacy ListView <ListView android:id="@+id/book_list_view" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"

    /> private val bookListView = findViewById<ListView>(R.id.book_list_view) val bookItems : List<Book> = datasource.getBooks() val adapter = ArrayAdapter(this,android.R.layout.simple_list_item_1, bookItems) bookListView.adapter = adapter
  2. Custom Adapter class BookAdapter: BaseAdapter() { override fun getCount(): Int

    = dataSource.size override fun getItem(position: Int): Any = dataSource[position] override fun getItemId(position: Int): Long = position.toLong() override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val rowView = inflater.inflate(R.layout.list_book_item, parent, false) val titleTextView = rowView.findViewById(R.id.book_title) as TextView val authorTextView = rowView.findViewById(R.id.book_author) as TextView // populate book data to itemview val book = getItem(position) as Book titleTextView.text = book.title authorTextView.text = book.author return rowView } }
  3. ViewHolder Pattern private class ViewHolder { lateinit var titleTextView: TextView

    lateinit var authorTextView: TextView } override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val rowView = inflater.inflate(R.layout.list_book_item, parent, false) val holder: ViewHolder = ViewHolder() holder.titleTextView = view.findViewById(R.id.book_title) as TextView holder.authorTextView = view.findViewById(R.id.book_author) as TextView // populate book data to itemview val book = getItem(position) as Book holder.titleTextView.text = book.title holder.authorTextView.text = book.author return rowView }
  4. RecyclerView “RecyclerView is a UI element to efficiently display large

    sets of data.” Viewport Scrap View scrolling Recycle Views Dirty View
  5. RecyclerView • ViewGroup containing views for the data • Mandatory

    ViewHolder defining each of the element - recyclerview binds the viewholder to the data • Adapter defines methods where view is requested and binds to data • LayoutManager arranges the items in the list
  6. class MyRecyclerAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder>() { class ViewHolder(view:

    View) : RecyclerView.ViewHolder(view) { val textView: TextView init { textView = view.findViewById(R.id.textView) } } override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { viewHolder.textView.text = dataSet[position] } override fun getItemCount() = dataSet.size }
  7. Recyclerview over ListView • Compulsory ViewHolder Pattern • Required Layout

    Manager • Item Animator • Item Decorator • Customizations for interaction with list item • Optimized performance
  8. Recyclerview with Multiple type views companion object { const val

    BOOK_TYPE = 0 const val GENRE_TYPE = 1 } sealed class DataItem(val type: Int) { class BookItem(val book: Book): DataItem(BOOK_TYPE) class GenreItem(val genreName: String): DataItem(GENRE_TYPE) } override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): RecyclerView.ViewHolder { return when (viewType) { BOOK_TYPE -> BookViewHolder(parent) GENRE_TYPE -> GenreViewHolder(parent) } } Book 1 Book 2 Genre 1 Genre 2 Book 1
  9. Recyclerview with Multiple type views override fun getItemViewType(position: Int): Int

    = dataSet[position].type override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val viewType = getItemViewType(position) val item = dataSet[position] when (viewType) { BOOK_TYPE -> { (holder as BookViewHolder).bind(item) } GENRE_TYPE -> { (holder as GenreViewHolder).bind(item) } } } Book 1 Book 2 Genre 1 Genre 2 Book 1
  10. ConcatAdapter Sequentially combine multiple adapters into a single RecyclerView val

    adapterOne: AdapterOne = {} val adapterTwo: AdapterTwo = {} val adapterThree: AdapterThree = {} val concatAdapter = ConcatAdapter(adapterOne, adapterTwo, adapterThree) recyclerView.adapter = concatAdapter ConcatAdapters
  11. Nested RecyclerView SearchBar Parent RecyclerView Activity/Fragment Category Name Child Recyclerview

    Parent recyclerview item Child recyclerview item CardView TextView
  12. Recyclerview in Compose @Composable fun DogListingScreen(viewModel: DogListingViewModel) { val dogs

    = viewModel.dogsList.observeAsState(initial = emptyList()) LazyColumn( contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) ) { items( items = dogs, itemContent = { DogListItem(dog = it) }) } } djain2405/jetpack-compose-adopt-happily
  13. Summary • A flexible view for providing a limited window

    into a large data set. • Faster , optimized performance • Versatile API • Recycled Views , dynamic list of data • Reduction in memory/power consumption • Enhanced responsiveness