package com.example.myapp.ui.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.myapp.databinding.ItemPostBinding
import com.example.myapp.models.Post
class PostsAdapter(
private val onPostClick: (Post) -> Unit,
private val onLikeClick: (Post) -> Unit = {}
) : ListAdapter<Post, PostsAdapter.PostViewHolder>(PostDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
val binding = ItemPostBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return PostViewHolder(binding, onPostClick, onLikeClick)
}
override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
holder.bind(getItem(position))
}
class PostViewHolder(
private val binding: ItemPostBinding,
private val onPostClick: (Post) -> Unit,
private val onLikeClick: (Post) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(post: Post) {
binding.apply {
titleText.text = post.title
bodyText.text = post.body
authorText.text = post.author
likesText.text = "${post.likesCount} likes"
timestampText.text = formatTimestamp(post.createdAt)
likeButton.setImageResource(
if (post.isLiked) R.drawable.ic_liked else R.drawable.ic_like
)
root.setOnClickListener { onPostClick(post) }
likeButton.setOnClickListener { onLikeClick(post) }
}
}
private fun formatTimestamp(timestamp: Long): String {
val now = System.currentTimeMillis()
val diff = now - timestamp
val seconds = diff / 1000
val minutes = seconds / 60
val hours = minutes / 60
val days = hours / 24
return when {
days > 0 -> "$days days ago"
hours > 0 -> "$hours hours ago"
minutes > 0 -> "$minutes minutes ago"
else -> "Just now"
}
}
}
class PostDiffCallback : DiffUtil.ItemCallback<Post>() {
override fun areItemsTheSame(oldItem: Post, newItem: Post): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Post, newItem: Post): Boolean {
return oldItem == newItem
}
override fun getChangePayload(oldItem: Post, newItem: Post): Any? {
return if (oldItem.likesCount != newItem.likesCount ||
oldItem.isLiked != newItem.isLiked) {
"LIKES_CHANGED"
} else {
null
}
}
}
}
package com.example.myapp.ui.adapters
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
class SwipeToDeleteCallback(
private val onDelete: (Int) -> Unit
) : ItemTouchHelper.SimpleCallback(
0,
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.adapterPosition
onDelete(position)
}
}
// Usage in Fragment:
// val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback { position ->
// viewModel.deletePost(adapter.currentList[position])
// })
// itemTouchHelper.attachToRecyclerView(binding.recyclerView)
RecyclerView displays large datasets efficiently with view recycling. I create a ViewHolder to cache view references and an Adapter to bind data. DiffUtil calculates minimal updates using areItemsTheSame and areContentsTheSame callbacks, improving performance over notifyDataSetChanged(). ListAdapter simplifies DiffUtil usage with background diffing. ItemTouchHelper adds swipe and drag gestures. ConcatAdapter combines multiple adapters. Layout managers control positioning—LinearLayoutManager for lists, GridLayoutManager for grids, StaggeredGridLayoutManager for Pinterest-style layouts. ViewBinding eliminates findViewById. Pagination libraries load data incrementally. RecyclerView powers most scrolling lists in Android apps.
Related snips
package com.example.myapp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
Dependency injection with Hilt
package com.example.myapp.ui
import androidx.lifecycle.*
import kotlinx.coroutines.launch
class UserViewModel(
LiveData transformations and mediators
<h1>Products</h1>
<%= form_with url: products_path, method: :get,
data: { turbo_frame: "products_list", turbo_action: "advance" } do |f| %>
<div class="filters">
<%= f.text_field :q, value: params[:q], placeholder: "Search products" %>
Frame navigation that targets a specific frame via form_with
package com.example.myapp.utils
import android.os.Build
import android.os.StrictMode
import android.os.Trace
import timber.log.Timber
Performance optimization and profiling
import SwiftUI
struct CardModifier: ViewModifier {
var backgroundColor: Color = .white
var cornerRadius: CGFloat = 12
var shadowRadius: CGFloat = 5
Custom SwiftUI view modifiers for reusability
package com.example.myapp.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
App widgets for home screen
Share this code
Here's the card — post it anywhere.