RecyclerView+Databinding最佳实践
📢Hello大家好,这里是码上夏雨,一名安卓初学者,也会定期给大家带来自己的学习心得📢
🤔这次带给大家的是安卓架构组件的数据绑定库方面的内容,如果你对此感兴趣也可以查看官方文档数据绑定库🤔
😍那事不宜迟,我们现在就发车😍
添加DataBinding支持
要将应用配置为使用数据绑定,请在应用模块的 build.gradle
文件中添加 dataBinding
元素,如以下示例所示:
//开启dataBinding
dataBinding {
enabled = true
}
![添加DataBinding支持](https://i-blog.csdnimg.cn/blog_migrate/745a53701de806b059af52866fcd97db.png)
数据准备
对于 RecyclerView
我们首先要准备的就是数据,那么我们这次需要让 RecyclerView
同时适配文字和图片展示,我们先来看看model的定义
😎对于图片,我们只需要使其包含一个 drawable
属性即可
class Image(var drawable: Drawable):BindingAdapterItem {
override fun getViewType(): Int {
return R.layout.image_item
}
}
😀对于文字,只需要使其包含一个 text
属性即可
class Text(val text: String):BindingAdapterItem {
override fun getViewType(): Int {
return R.layout.text_item
}
}
使用数据绑定库
布局和绑定表达式
借助表达式语言,您可以编写将变量关联到布局中的视图的表达式。数据绑定库会自动生成将布局中的视图与您的数据对象绑定所需的类。该库提供了可在布局中使用的导入、变量和包含等功能。
该库的这些功能可与您的现有布局无缝地共存。例如,可以在表达式中使用的绑定变量在 data 元素(界面布局根元素的同级)内定义。这两个元素都封装在 layout 标记中,如以下示例所示:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="com.gcode.databindingsample.model.Text" />
</data>
<ConstraintLayout... /> <!-- UI layout's root element -->
</layout>
带有ID的视图
数据绑定库会针对布局中具有 ID 的每个视图在绑定类中创建不可变字段。例如,以我们创建的 Text
对象来说,我们已经在 data
里面声明了它的 name
和对应的类型 type
,数据绑定库会根据以下布局创建 TextView 类型的 text 字段:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="com.gcode.databindingsample.model.Text" />
</data>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{item.text}"
android:gravity="center"
android:textSize="25sp"/>
</layout>
适配器的准备
😗 我们首先来看一下适配器的完整代码
class BindingAdapter(var items: MutableList<BindingAdapterItem>) : RecyclerView.Adapter<BindingAdapter.BindingHolder>() {
/**
* @return 返回的是adapter的view
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder {
val binding = DataBindingUtil.inflate<ViewDataBinding>(
LayoutInflater.from(parent.context),
viewType,
parent,
false
)
return BindingHolder(binding)
}
/**
* 数据绑定
*/
override fun onBindViewHolder(holder: BindingHolder, position: Int) {
holder.bindData(items[position])
}
override fun getItemCount() = items.size
override fun getItemViewType(position: Int) = items[position].getViewType()
class BindingHolder(var binding: ViewDataBinding) : ViewHolder(binding.root) {
fun bindData(item: BindingAdapterItem?) {
binding.setVariable(BR.item, item)
}
}
}
🤔首先我们在使用 DataBindingUtil.inflate()
时会用到 viewType
,它是在 fun getItemViewType(position: Int)
里面设置获取的,因此我们可以声明一个接口,并让自己的model实现这个接口
interface BindingAdapterItem {
fun getViewType(): Int
}
😚类内实现,这里我们也看到 getViewType()
返回的是item对应的布局id
class Image(var drawable: Drawable) : BindingAdapterItem {
override fun getViewType(): Int {
return R.layout.image_item //Image对象使用的布局id
}
}
😲然后重写Adapter里面的 getItemViewType
方法,这样就可以获取到不同item对应的ViewType了
override fun getItemViewType(position: Int) = items[position].getViewType()
![nice](https://i-blog.csdnimg.cn/blog_migrate/8a0b67233ec3e0d494965b9cd44b19d6.png)
😄同时,有时系统并不知道特定的绑定类。例如,针对任意布局运行的 RecyclerView.Adapter 不知道特定绑定类。在调用 onBindViewHolder()
方法时,仍必须指定绑定值。我们在这里需要使用 setVariable
方法
binding.setVariable(BR.item, item)
注意:数据绑定库在模块包中生成一个名为 BR 的类,其中包含用于数据绑定的资源的 ID。在上例中,该库自动生成 BR.item 变量。
![good](https://i-blog.csdnimg.cn/blog_migrate/00f0af19654fff08093c628deaf06245.png)
😎到这里为止我们就完成了所有内容,我们准备好数据,来看一下效果
![](https://img-blog.csdnimg.cn/42610dd1a8f2464a993a8f8475e30ea4.gif)
代码部分
编写代码不易,如果你觉得我的项目帮到了你,欢迎star fork,你的支持是我编写代码的动力!
完整代码参考AndroidHappyClub/DataBindingBasic,同时根据这种设计思想我设计了适用于RecyclerView的通用VastAdapter,点击即可查看详细内容,关于VastAdapter的介绍可以查看通用RecyclerView Adapter