The best examples of Kotlin RecyclerView – 3 practical use cases for modern Android apps
Why RecyclerView still matters in 2024
Jetpack Compose is getting most of the headlines, but RecyclerView is very much alive in production apps. Many teams are:
- Maintaining large legacy codebases that depend on RecyclerView.
- Shipping hybrid UIs where fragments and activities still host RecyclerView-based screens.
- Using RecyclerView for advanced layouts (carousels, grids, drag-and-drop) that still feel more familiar than Compose equivalents.
So learning from examples of Kotlin RecyclerView is still a smart investment. The best examples don’t just show how to display a list; they show how to manage state, performance, and interaction patterns you see in real apps.
Use Case 1: Chat-style list with multiple view types
If you’re looking for examples of Kotlin RecyclerView examples – 3 practical use cases that feel like real products, chat UIs are at the top of the list. Almost every messaging screen uses some form of RecyclerView with multiple view types.
Core idea
You have a list of messages where each item can be:
- A message sent by the user
- A message received from another user
- A system event ("User joined”, “Message deleted")
This is a classic example of multiple view types in a single RecyclerView.
Data model
sealed class ChatItem {
data class OutgoingMessage(
val id: Long,
val text: String,
val timestamp: Long
) : ChatItem()
data class IncomingMessage(
val id: Long,
val senderName: String,
val text: String,
val timestamp: Long
) : ChatItem()
data class SystemEvent(
val id: Long,
val text: String,
val timestamp: Long
) : ChatItem()
}
Adapter with multiple view types
class ChatAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val items = mutableListOf<ChatItem>()
companion object {
private const val TYPE_OUTGOING = 1
private const val TYPE_INCOMING = 2
private const val TYPE_SYSTEM = 3
}
fun submitList(newItems: List<ChatItem>) {
items.clear()
items.addAll(newItems)
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int = when (items[position]) {
is ChatItem.OutgoingMessage -> TYPE_OUTGOING
is ChatItem.IncomingMessage -> TYPE_INCOMING
is ChatItem.SystemEvent -> TYPE_SYSTEM
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
TYPE_OUTGOING -> {
val view = inflater.inflate(R.layout.item_outgoing_message, parent, false)
OutgoingViewHolder(view)
}
TYPE_INCOMING -> {
val view = inflater.inflate(R.layout.item_incoming_message, parent, false)
IncomingViewHolder(view)
}
else -> {
val view = inflater.inflate(R.layout.item_system_event, parent, false)
SystemViewHolder(view)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (val item = items[position]) {
is ChatItem.OutgoingMessage -> (holder as OutgoingViewHolder).bind(item)
is ChatItem.IncomingMessage -> (holder as IncomingViewHolder).bind(item)
is ChatItem.SystemEvent -> (holder as SystemViewHolder).bind(item)
}
}
override fun getItemCount(): Int = items.size
class OutgoingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: ChatItem.OutgoingMessage) {
// bind views here
}
}
class IncomingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: ChatItem.IncomingMessage) {
// bind views here
}
}
class SystemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: ChatItem.SystemEvent) {
// bind views here
}
}
}
This pattern is one of the best examples of how RecyclerView can handle rich, heterogeneous content without becoming unmanageable.
Other real examples that use this pattern
Real-world screens that mirror this approach include:
- Notification centers mixing different notification types.
- Activity feeds with posts, comments, and system badges.
- E-commerce order timelines (order placed, shipped, delivered, refunded).
All of these are examples of Kotlin RecyclerView where multiple view types keep your code organized and your UI flexible.
Use Case 2: Paginated feed with Paging 3 and Kotlin coroutines
Infinite scrolling feeds are everywhere: social media, product catalogs, search results. When people ask for examples of Kotlin RecyclerView examples – 3 practical use cases, a paginated feed is almost always on the list.
For 2024 and beyond, the recommended approach is Paging 3 with Kotlin coroutines and Flow.
PagingSource implementation
class ArticlesPagingSource(
private val api: ArticlesApi
) : PagingSource<Int, Article>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Article> {
return try {
val page = params.key ?: 1
val response = api.getArticles(page = page, pageSize = params.loadSize)
LoadResult.Page(
data = response.items,
prevKey = if (page == 1) null else page - 1,
nextKey = if (response.items.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, Article>): Int? {
return state.anchorPosition?.let { anchor ->
val anchorPage = state.closestPageToPosition(anchor)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}
Pager and Flow in a repository
class ArticlesRepository(private val api: ArticlesApi) {
fun getArticlesStream(): Flow<PagingData<Article>> {
return Pager(
config = PagingConfig(
pageSize = 20,
enablePlaceholders = false,
prefetchDistance = 2
),
pagingSourceFactory = { ArticlesPagingSource(api) }
).flow
}
}
PagingDataAdapter for RecyclerView
class ArticlesAdapter(
private val onArticleClick: (Article) -> Unit
) : PagingDataAdapter<Article, ArticlesAdapter.ArticleViewHolder>(DIFF_CALLBACK) {
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Article>() {
override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean =
oldItem == newItem
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_article, parent, false)
return ArticleViewHolder(view, onArticleClick)
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
class ArticleViewHolder(
itemView: View,
private val onArticleClick: (Article) -> Unit
) : RecyclerView.ViewHolder(itemView) {
fun bind(article: Article) {
// bind views here
itemView.setOnClickListener { onArticleClick(article) }
}
}
}
Collecting data in a Fragment
@AndroidEntryPoint
class ArticlesFragment : Fragment(R.layout.fragment_articles) {
private val viewModel: ArticlesViewModel by viewModels()
private val adapter = ArticlesAdapter { article ->
// handle clicks
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.articles.collectLatest { pagingData ->
adapter.submitData(pagingData)
}
}
}
}
}
This is one of the best examples of a modern Kotlin RecyclerView setup: reactive, paginated, and production-ready.
Other real examples that mirror this pattern
Other examples include:
- Product lists in shopping apps with endless scroll.
- Search result screens that load more as you scroll.
- News feeds or blog lists pulling from a REST API.
- User directories or follower lists in social apps.
All of these are reliable examples of Kotlin RecyclerView integrated with Paging 3 and coroutines.
Use Case 3: Drag-and-drop reordering with ItemTouchHelper
Another example of RecyclerView that shows up in real apps is drag-and-drop reordering. Think of apps where users can:
- Reorder playlists.
- Prioritize tasks in a to-do list.
- Customize home screen sections or dashboards.
This is where ItemTouchHelper comes in.
Basic setup
class ReorderableAdapter(
private val items: MutableList<String>
) : RecyclerView.Adapter<ReorderableAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_reorderable, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
fun moveItem(fromPosition: Int, toPosition: Int) {
if (fromPosition == toPosition) return
val moved = items.removeAt(fromPosition)
items.add(toPosition, moved)
notifyItemMoved(fromPosition, toPosition)
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(text: String) {
// bind views here
}
}
}
ItemTouchHelper callback
class DragManageAdapter(
private val adapter: ReorderableAdapter
) : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
val swipeFlags = 0
return makeMovementFlags(dragFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
adapter.moveItem(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
// No swipe support here
}
override fun isLongPressDragEnabled(): Boolean = true
}
Attaching to RecyclerView
val adapter = ReorderableAdapter(mutableListOf("One", "Two", "Three"))
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
val callback = DragManageAdapter(adapter)
val touchHelper = ItemTouchHelper(callback)
touchHelper.attachToRecyclerView(recyclerView)
This pattern is a practical example of Kotlin RecyclerView for interactive UIs where the user is in control of ordering.
Other real examples using drag-and-drop
You’ll see similar behavior in:
- Music apps letting users reorder songs in a queue.
- Note-taking apps where sections can be rearranged.
- Settings screens where quick actions can be reordered.
These are all examples of RecyclerView providing a more tactile, user-driven experience.
Six more real examples of Kotlin RecyclerView in production-style UIs
To go beyond the three main scenarios, here are more real examples you’ll encounter often:
- A horizontal carousel of featured items on a home screen using
LinearLayoutManagerwithHORIZONTALorientation. - A grid of photos or products using
GridLayoutManager, with span sizes adjusted for featured items. - A settings screen where sections and toggles are all backed by a single RecyclerView with multiple view types.
- A favorites list with swipe-to-delete using
ItemTouchHelperfor swipe gestures only. - A calendar-like list of events grouped by date, using sticky headers implemented as another view type.
- A download manager screen that updates progress bars in each item as downloads progress via
FloworLiveData.
Each of these is an example of how flexible RecyclerView is when combined with Kotlin, coroutines, and the rest of the Jetpack stack.
RecyclerView vs. Jetpack Compose in 2024–2025
You can’t talk about examples of Kotlin RecyclerView in 2024 without acknowledging Jetpack Compose. Google’s own guidance, as of 2024, is that Compose is the recommended path for new UI development, but RecyclerView is still widely supported and documented.
Some teams are:
- Keeping existing RecyclerView screens and writing new ones in Compose.
- Embedding Compose inside RecyclerView items using
ComposeViewfor gradual migration. - Using RecyclerView for very large lists where they already have tuned performance and caching.
The Android docs on Compose interoperability show how both approaches can coexist. So learning from solid examples of Kotlin RecyclerView examples – 3 practical use cases still pays off, even if your long-term strategy is Compose.
FAQ: Kotlin RecyclerView examples
What are the most common examples of Kotlin RecyclerView in real apps?
Some of the best examples include chat lists, infinite feeds with Paging 3, drag-and-drop task lists, swipe-to-delete email lists, and grid-based galleries. All of them share the same building blocks: a RecyclerView, a Kotlin-based adapter, and a layout manager.
Can you show a simple example of a Kotlin RecyclerView adapter?
class SimpleStringAdapter(
private val items: List<String>
) : RecyclerView.Adapter<SimpleStringAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_simple_text, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(text: String) {
// bind text to TextView
}
}
}
While basic, this is often the first example of Kotlin RecyclerView that beginners implement before moving to more advanced patterns.
Is RecyclerView still worth learning with Jetpack Compose available?
Yes. Many organizations have large RecyclerView-based codebases that will be around for years. Hiring managers still expect Android developers to understand RecyclerView, DiffUtil, and adapters. Knowing modern examples of Kotlin RecyclerView also makes it easier to reason about how lists work in Compose, because the underlying performance considerations are similar.
Where can I find official guidance and patterns?
For official Android patterns and updated guidance, check:
- Android’s RecyclerView docs: https://developer.android.com/guide/topics/ui/layout/recyclerview
- Android Architecture Components and Paging: https://developer.android.com/topic/libraries/architecture/paging
These references complement the examples of Kotlin RecyclerView examples – 3 practical use cases in this article with deeper API details and best practices.
Related Topics
Real-world examples of diverse Kotlin coroutines in 2025
The best examples of Kotlin RecyclerView – 3 practical use cases for modern Android apps
Modern examples of 3 practical examples of Kotlin sealed classes in real apps
Real‑world examples of diverse Kotlin data classes for modern development
Explore More Kotlin Code Snippets
Discover more examples and insights in this category.
View All Kotlin Code Snippets