Skip to content

Instantly share code, notes, and snippets.

@Krosxx
Created July 16, 2020 06:26
Show Gist options
  • Save Krosxx/1ea1efd1011e5c61792b4d5cc9790c94 to your computer and use it in GitHub Desktop.
Save Krosxx/1ea1efd1011e5c61792b4d5cc9790c94 to your computer and use it in GitHub Desktop.
DataBindingAdapter for RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import kotlin.reflect.KClass
/**
* # MultiTypeBindingAdapter
*
* Created on 2020/6/16
* @author Vove
*/
fun multiTypeBindingAdapter(
dataSet: List<Any>,
dbIdLayoutGetter: (item: Any) -> Pair<Int, Int>
): MultiTypeBindingAdapter {
return MultiTypeBindingAdapter(dataSet, dbIdLayoutGetter)
}
fun <T : Any> bindingAdapter(
dataSet: List<T>,
dbId: Int,
layId: Int
): BindingAdapter<T> = BindingAdapter(dataSet, dbId, layId)
open class MultiTypeBindingAdapter(
private val dataSet: List<Any>,
val dbIdLayoutGetter: (typeCls: KClass<*>) -> Pair<Int, Int>
) : RecyclerView.Adapter<BindingViewHolder>() {
private val typeMap = mutableMapOf<Int, KClass<*>>()
private fun getItem(p: Int): Any = dataSet[p]
override fun getItemViewType(position: Int): Int {
val type = (getItem(position) as Object).`class`.name.hashCode()
typeMap[type] = getItem(position)::class
return type
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder {
val (dbId, lId) = dbIdLayoutGetter(typeMap[viewType]!!)
val binding = DataBindingUtil.inflate<ViewDataBinding>(
LayoutInflater.from(parent.context),
lId,
parent,
false
)
return BindingViewHolder(binding.root.also {
it.setTag(R.id.tag_adapter_databinding_support, binding)
}, dbId)
}
override fun getItemCount(): Int = dataSet.size
override fun onBindViewHolder(holder: BindingViewHolder, position: Int) {
holder.binding.apply {
setVariable(holder.dbId, dataSet[position])
executePendingBindings()
}
}
}
open class BindingAdapter<T : Any>(
dataSet: List<T>,
private val dbId: Int,
private val layId: Int
) : MultiTypeBindingAdapter(dataSet, { dbId to layId })
class BindingViewHolder(itemView: View, val dbId: Int) : RecyclerView.ViewHolder(itemView) {
val binding: ViewDataBinding
get() = itemView.getTag(R.id.tag_adapter_databinding_support) as ViewDataBinding
}
@Krosxx
Copy link
Author

Krosxx commented Jul 16, 2020

单一类型数据

数据类:

data class ListItem(
    val id: Int,
    val name: String
)

列表布局(item_demo_list.xml):

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="item"
            type="xxx.model.ListItem" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">
        <TextView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:gravity="center"
            android:text="@{String.valueOf(item.id)}"
            android:textSize="20sp"
            android:textStyle="bold" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{item.name}" />
    </LinearLayout>
</layout>

创建 Adapter :

recyclerView.adapter = bindingAdapter(multiList, BR.item, R.layout.item_demo_list)

@Krosxx
Copy link
Author

Krosxx commented Jul 16, 2020

多种布局类型:

添加一个数据类:

data class ListItem2(val icon: String)

布局 item_demo_list2.xml 省略...

创建Adapter:

recyclerView.adapter = multiTypeBindingAdapter(multiList) { kcls ->
    when (kcls) {
        ListItem::class -> BR.item to R.layout.item_demo_list
        ListItem2::class -> BR.item2 to R.layout.item_demo_list2
        else -> throw Exception("unsupport type $kcls")
    }
}

@Krosxx
Copy link
Author

Krosxx commented Jul 16, 2020

也可以继承其他已封装的Adapter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment