美文网首页
RecyclerView(6) 搭配使用 DataBinding

RecyclerView(6) 搭配使用 DataBinding

作者: 行走中的3卡 | 来源:发表于2022-12-07 09:35 被阅读0次

    目的是:设置数据绑定,并消除对 findViewById() 的调用

    和前面系列文章一样, 关注 DataBinding /BindingAdapter 在RecyclerView 上的使用思想, 忽略具体的代码细节.

    1.向布局文件 添加 数据绑定

    (1)在 Code 标签页中打开 list_item_sleep_night.xml 布局文件。
    将光标放在 ConstraintLayout 标签上,然后按 Alt+Enter
    系统随即会打开 intent 菜单(“quick fix”菜单)。
    (2)选择 Convert to data binding layout。这会将布局封装到 <layout> 中,并在其中添加 <data> 标签。
    (3)根据需要滚动回顶部,并在 <data> 标签内声明一个名为 sleep 的变量。
    (4)将其 type 设为 SleepNight 的完全限定名称
    com.example.android.trackmysleepquality.database.SleepNight。
    完成后的 <data> 标签应如下所示:

    <layout
       <data>
            <variable
                name="sleep"
                type="com.example.android.trackmysleepquality.database.SleepNight"/>
        </data>
    </layout>   
    

    可见,加了一层 父布局 <layout>

    (5) 如需强制创建 Binding 对象,请依次选择 Build > Clean Project,
    然后依次选择 Build > Rebuild Project。
    (如果仍然存在问题,请依次选择 File > Invalidate Caches / Restart。)
    ListItemSleepNightBinding 绑定对象以及相关代码会添加到项目生成的文件中。

    2. 第 2 步:使用 数据绑定 加载 项布局

    SleepNightAdapter 的ViewHolder 中,
    删除:

    val view = layoutInflater
           .inflate(R.layout.list_item_sleep_night, parent, false)
    

    增加:

    val binding =
    ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
    

    修改:

    return ViewHolder(binding) // 参数为 ListItemSleepNightBinding
    
    //参数为 ListItemSleepNightBinding 且 binding.root 为根View (例子中的ConstraintLayout)
    lass ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
    

    此外, ViewHolder 中的自定的变量也可删掉,使用binding.xxx.

    至此, 使用了DataBinding 取代了 findViewById 的操作,
    通过 布局对应的 Binding 类, 直接获取到 控件.

    例如:
    android:id="@+id/quality_string" ====> binding.qualityString
    注意: 会把下划线去掉, 变成驼峰式变量名

    3. 创建 绑定适配器 BindingAdapter

    绑定适配器 会获取数据特别是复杂的,
    并将其调整为可供数据绑定功能用于绑定视图(例如文本或图片)的内容

    实现三个绑定适配器,一个用于高质量图片,另外两个分别用于一个文本字段

    要定义一种获取项和视图的方法,并用 @BindingAdapter 进行注解

    在 Kotlin 中,可以在接收数据的视图类上将 绑定适配器编写为 扩展函数

    3.1 创建 BindingAdapter 声明的函数

    其实这里就是为了 将 SleepNight 数据, 转换成 能够在 View 上显示的数据(文本、图片)
    创建 BindingUtils.kt, 用于创建 静态函数

    class BindingUtils {}
    

    (1) 睡眠时间 sleepDurationFormatted
    在 TextView 上声明一个名为 setSleepDurationFormatted 的扩展函数
    将数据绑定到视图,如在 ViewHolder.bind() 中一样.
    请使用 @BindingAdapter 为该函数添加注解, 向数据绑定功能告知此绑定适配器.

    @BindingAdapter("sleepDurationFormatted")
    fun TextView.setSleepDurationFormatted(item: SleepNight) {
       text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
    }
    

    (2) 睡眠质量 sleepQualityString

    @BindingAdapter("sleepQualityString")
    fun TextView.setSleepQualityString(item: SleepNight) {
       text = convertNumericQualityToString(item.sleepQuality, context.resources)
    }
    

    (3)sleepImage

    @BindingAdapter("sleepImage")
    fun ImageView.setSleepImage(item: SleepNight) {
       setImageResource(when (item.sleepQuality) {
           0 -> R.drawable.ic_sleep_0
           1 -> R.drawable.ic_sleep_1
           2 -> R.drawable.ic_sleep_2
           3 -> R.drawable.ic_sleep_3
           4 -> R.drawable.ic_sleep_4
           5 -> R.drawable.ic_sleep_5
           else -> R.drawable.ic_sleep_active
       })
    }
    

    这个相对简单了.

    3.2 在ViewHolder 中为 布局文件 设置 数据类对象.

        class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root) {
    
            fun bind(
                item: SleepNight
            ) {
                binding.sleep = item
                // 此调用是一种优化,用于要求数据绑定功能立即执行任何待处理的绑定
                // 当您在 RecyclerView 中使用绑定适配器时,最好调用 executePendingBindings(),因为它可以略微加快调整视图大小的过程
                binding.executePendingBindings()
    /*     // 可以使用 Databinding 和 BindingAdapter 执行
                val res = itemView.context.resources
                binding.sleepLength //取代  viewHolder.findViewById(R.id.sleep_length)
                    .text = convertDurationToFormatted(
                    item.startTimeMilli, item.endTimeMilli, res
                )
    
                binding.qualityString.text = convertNumericQualityToString(item.sleepQuality, res)
                binding.qualityImage.setImageResource(
                    when (item.sleepQuality) {
                        0 -> R.drawable.ic_sleep_0
                        1 -> R.drawable.ic_sleep_1
                        2 -> R.drawable.ic_sleep_2
                        3 -> R.drawable.ic_sleep_3
                        4 -> R.drawable.ic_sleep_4
                        5 -> R.drawable.ic_sleep_5
                        else -> R.drawable.ic_sleep_active
                    }
                )
     */
            }
    

    注意: 需要在 类的顶级, 即在类体外部

    3.3 向 XML 布局添加绑定

    为文本、图片View 添加 绑定 (数据类)
    因为 3.1 中创建的 BindingAdapter 函数 都需要一个参数 SleepNight(这里是sleep对象)

    app:sleepImage="@{sleep}"
    
    app:sleepDurationFormatted="@{sleep}"
    
    app:sleepQualityString="@{sleep}"
    

    至此,已完成所有.

    参考文献:
    https://developer.android.com/codelabs/kotlin-android-training-diffutil-databinding?hl=zh-cn#6
    完整代码:
    https://github.com/google-developer-training/android-kotlin-fundamentals-apps/tree/master/RecyclerViewDiffUtilDataBinding

    相关文章

      网友评论

          本文标题:RecyclerView(6) 搭配使用 DataBinding

          本文链接:https://www.haomeiwen.com/subject/brnefdtx.html