Skip to content

Instantly share code, notes, and snippets.

@Holofox
Created July 30, 2019 10:46
Show Gist options
  • Save Holofox/bac89e9eb85e68e0e5d9894e73666790 to your computer and use it in GitHub Desktop.
Save Holofox/bac89e9eb85e68e0e5d9894e73666790 to your computer and use it in GitHub Desktop.
DataBindingAdapter for RecyclerView (MVVM)
abstract class DataBindingAdapter<T>(
private val variableId: Int,
diffCallback: DiffUtil.ItemCallback<T>
) : ListAdapter<T, DataBindingAdapter.DataBindingViewHolder<T>>(diffCallback) {
private var list: List<T>? = emptyList()
private lateinit var onItemViewClick: ((View, T, Int) -> Unit?)
private lateinit var clickableIds: IntArray
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBindingViewHolder<T> {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = DataBindingUtil.inflate<ViewDataBinding>(layoutInflater, viewType, parent, false)
return DataBindingViewHolder(binding, variableId)
}
override fun onBindViewHolder(holder: DataBindingViewHolder<T>, position: Int) {
holder.apply {
bind(getItem(position))
if (::onItemViewClick.isInitialized && ::clickableIds.isInitialized) {
val clickListener = View.OnClickListener { view ->
list?.get(holder.adapterPosition)?.let {
onItemViewClick.invoke(view, it, holder.adapterPosition)
}
}
for (clickableId in clickableIds) {
holder.itemView.findViewById<View>(clickableId)?.setOnClickListener(clickListener)
}
}
}
}
override fun submitList(list: List<T>?) {
super.submitList(list)
this.list = list
}
fun setOnItemViewClickListener(
onItemViewClick: (view: View, model: T, position: Int) -> Unit,
vararg ids: Int
) {
this.onItemViewClick = onItemViewClick
this.clickableIds = ids
}
class DataBindingViewHolder<T>(
private val binding: ViewDataBinding,
private val variableId: Int
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: T) {
binding.setVariable(variableId, item)
binding.executePendingBindings()
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="postponedListModel"
type="ru.holofox.anicoubs.data.db.unitlocalized.vk.UnitSpecificVKWallMinimalEntry" />
</data>
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardView_postponed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?listPreferredItemHeightLarge"
android:layout_margin="4dp"
app:cardCornerRadius="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?listPreferredItemHeightLarge">
<!-- ... -->
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
class PostponedAdapter :
DataBindingAdapter<UnitSpecificVKWallMinimalEntry>(BR.postponedListModel, DiffCallback()) {
class DiffCallback : DiffUtil.ItemCallback<UnitSpecificVKWallMinimalEntry>() {
override fun areItemsTheSame(
oldItem: UnitSpecificVKWallMinimalEntry,
newItem: UnitSpecificVKWallMinimalEntry
): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: UnitSpecificVKWallMinimalEntry,
newItem: UnitSpecificVKWallMinimalEntry
): Boolean = oldItem == newItem
}
override fun getItemViewType(position: Int) = R.layout.item_postponed
}
class PostponedListFragment : Fragment() {
...
private var viewModelAdapter: PostponedAdapter? = null
private val onItemMore: (View) -> Unit = { }
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(
inflater,
R.layout.postponed_list_fragment,
container,
false
)
viewModelAdapter = PostponedListAdapter().apply {
setOnItemViewClickListener({view, model, position ->
when (view.id) {
R.id.cardView_postponed -> showPostponedDetail(view)
R.id.imageView_more -> onItemMore(view)
}
}, R.id.imageView_more, R.id.cardView_postponed)
}
binding.apply {
lifecycleOwner = viewLifecycleOwner
postponedViewModel = viewModel
recyclerView.adapter = viewModelAdapter
}
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.wall.observe(viewLifecycleOwner, Observer { entries ->
entries?.let {
viewModelAdapter?.submitList(entries)
}
})
}
private fun showPostponedDetail(view: View) { }
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment