RecyclerView
Android Development
Multiple View Types
Android Studio
Mobile App Development

How to create RecyclerView with multiple view types

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

RecyclerView is a versatile widget in Android development, providing a dynamic way to display a list of items using a small amount of memory. One powerful feature of RecyclerView is the ability to use multiple view types within a single list. This article explores how you can implement a RecyclerView with multiple view types, the technicalities involved, and best practices.

Understanding RecyclerView with Multiple View Types

In scenarios where the list you want to display isn't homogeneous, utilizing multiple view types can make your app's interface more informative and engaging. For instance, in a messaging app, you might want different layouts for sent messages, received messages, images, dates, etc. Employing multiple view types in RecyclerView starts with understanding the concept of ViewHolder patterns and item view types.

Preparing the Data Model

Before diving into the implementation, it's essential to structure your data model to support different types. A common approach is to create a base class with specific subclasses for each view type.

kotlin
1sealed class ListItem {
2    object Loading : ListItem()
3    data class TextMessage(val text: String): ListItem()
4    data class ImageMessage(val imageUrl: String): ListItem()
5}

Implementing the RecyclerView Adapter

The heart of handling multiple view types in RecyclerView lies in the adapter. An adapter works by coordinating with ViewHolder classes to display each type appropriately.

  1. Create ViewHolder Classes for Each View Type
    Each ViewHolder should correlate to a layout item.
kotlin
1    class TextMessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
2        fun bind(textMessage: ListItem.TextMessage) {
3            itemView.textView.text = textMessage.text
4        }
5    }
6
7    class ImageMessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
8        fun bind(imageMessage: ListItem.ImageMessage) {
9            // Use libraries like Glide to load the image
10            Glide.with(itemView).load(imageMessage.imageUrl).into(itemView.imageView)
11        }
12    }
  1. Override getItemViewType Method
    The adapter needs to override getItemViewType to instruct which layout to use for each item at a specific position.
kotlin
1    override fun getItemViewType(position: Int): Int {
2        return when (items[position]) {
3            is ListItem.TextMessage -> R.layout.item_text_message
4            is ListItem.ImageMessage -> R.layout.item_image_message
5            is ListItem.Loading -> R.layout.item_loading
6        }
7    }
  1. Override onCreateViewHolder and onBindViewHolder Methods
    With the item view type decided, create corresponding view holders in onCreateViewHolder and bind data in onBindViewHolder.
kotlin
1    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
2        val inflater = LayoutInflater.from(parent.context)
3        return when (viewType) {
4            R.layout.item_text_message -> {
5                val view = inflater.inflate(R.layout.item_text_message, parent, false)
6                TextMessageViewHolder(view)
7            }
8            R.layout.item_image_message -> {
9                val view = inflater.inflate(R.layout.item_image_message, parent, false)
10                ImageMessageViewHolder(view)
11            }
12            else -> throw IllegalStateException("Unexpected viewType $viewType")
13        }
14    }
15
16    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
17        when (val item = items[position]) {
18            is ListItem.TextMessage -> (holder as TextMessageViewHolder).bind(item)
19            is ListItem.ImageMessage -> (holder as ImageMessageViewHolder).bind(item)
20        }
21    }

Additional Considerations

  • Handling More Than Two View Types: The approach scales efficiently; continue to add cases for view types in the switch cases of getItemViewType and onBindViewHolder.
  • Adapter Optimization: Consider utilizing DiffUtil for efficient updates in data set changes.

Summary Table

Here's a quick summary of the critical concepts:

ConceptDescription
Data ModelUse a base class with specific subclasses for each view type
ViewHolderCreate specific view holders to handle each type
getItemViewTypeOverride to specify which layout belongs to each item
onCreateViewHolderInflate specific layouts and create ViewHolder instances for each view type
onBindViewHolderBind data based on the type of item using appropriate ViewHolder
OptimizationImprove performance using DiffUtil or other data set change handling mechanisms

Conclusion

Implementing RecyclerView with multiple view types necessitates a grasp of the core concepts of ViewHolder and item view types. By structuring your data correctly and managing layouts effectively, you not only save memory but also enhance user interaction by providing diverse, meaningful representations within a single list. Whether leveraging libraries or optimizing through advanced features, Android's RecyclerView provides a robust foundation for sophisticated apps.


Course illustration
Course illustration

All Rights Reserved.