美文网首页JetPack
Data Binding 笔记(一)

Data Binding 笔记(一)

作者: simple_jie | 来源:发表于2020-01-01 21:43 被阅读0次

    Android Studio 中开启 Data Binding

    android {
      dataBinding { enable true }
    }
    

    现有布局转换为 Data Binding 布局

    选中原根布局,使用快捷键 alt + enter 打开操作面板,选择“Convert to data binding layout”


    image.png

    会在原布局外面生成如下代码

    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data>
    
        </data>
    
         原布局...
      
    </layout>
    

    data 标记

    <data> 标记中将包含layout variables,layout variables 将用于编写 layout expressions
    layout expressions 用于给UI的属性赋值,格式为 @{ expression }
    layout variables 的值可以直接通过ViewDataBinding对象赋值参考后面 变量申明 部分

    例子如下

    // Some examples of complex layout expressions
    android:text="@{String.valueOf(index + 1)}"
    android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
    android:transitionName='@{"image_" + id}
    

    在Activity中初始化Data Binding对象

    Data binding 库会自动生成 xxxxActivityBinding 类, 用DataBindingUtil工具类如下初始化ViewDataBinding对象

    val binding: xxxxActivityBinding =
                DataBindingUtil.setContentView(this, R.layout.xxx_layout)
    

    操作符

    The expression language looks a lot like expressions found in managed code. You can use the following operators and keywords in the expression language:

    <table><tr><td bgcolor=orange>背景色是:orange</td></tr></table>

    • Mathematical + - / * %
      数学运算 加减乘除余
    • String concatenation +
      字符串链接
    • Logical && ||
      逻辑运算 与 或
    • Binary & | ^
      位运算
    • Unary + - ! ~
      一元操作符
    • Shift >> >>> <<
      移位操作
    • Comparison == > < >= <= (Note that < needs to be escaped as \color{Coral}{\&lt;})
      比较操作,小于符号需要用 &lt; 替换
    • instanceof
      类型判断
    • Grouping ()
      分组操作
    • Literals - character, String, numeric, null
    • Cast
    • Method calls
      方法调用
    • Field access
      字段属性访问
    • Array access []
      数组访问
    • Ternary operator ?:
      三元操作
    • ?? 空判断选择

    以下操作等效
    android:text="@{user.displayName ?? user.lastName}"
    android:text="@{user.displayName != null ? user.displayName : user.lastName}"

    集合应用示例

    <data>
        <import type="android.util.SparseArray"/>
        <import type="java.util.Map"/>
        <import type="java.util.List"/>
        <variable name="list" type="List&lt;String>"/>
        <variable name="sparse" type="SparseArray&lt;String>"/>
        <variable name="map" type="Map&lt;String, String>"/>
        <variable name="index" type="int"/>
        <variable name="key" type="String"/>
    </data>
    …
    android:text="@{list[index]}"
    …
    android:text="@{sparse[index]}"
    …
    android:text="@{map[key]}"
    

    字符串引用

    可以单引号和双引号结合使用的方式,达到应用字符串字面值的目的

    android:text='@{map["firstName"]}'
    android:text="@{map[`firstName`]}"
    

    资源引用

    android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
    //格式化字符串
    android:text="@{@string/nameFormat(firstName, lastName)}"
    android:text="@{@plurals/banana(bananaCount)}"
    

    变量申明

     <data>
        <import type="com.example.android.databinding.basicsample.R"/>
        <import type="com.example.android.databinding.basicsample.util.ConverterUtil"/>
        <variable
              name="user"
              type="com.example.android.databinding.basicsample.data.ObservableFieldProfile" />
    </data>
    

    通过 import 标记引入类型
    通过 variable 申明变量一个变量
    在xml中我们我们就可以直接用引入的类,和变量书写表达式

    <TextView
                android:id="@+id/name"
                android:text="@{user.name}"
    ...
    
                android:visibility="@{ConverterUtil.isZero(user.likes)}"
    

    结合ViewModel使用

    ViewModel申明了一个name的LiveData对象

    class SimpleViewModel : ViewModel() {
        private val _name = MutableLiveData("Tim")
        val name: LiveData<String> = _name
    

    在xml中直接申明一个ViewModel的变量,然后在后面的xml直接引用该liveData对象 @{viewmodel.name}

    <data
            <variable
                name="viewmodel"
                type="com.example.android.databinding.basicsample.data.SimpleViewModel"/>
    </data>
    <TextView
                android:text="@{viewmodel.name}"
    

    在Activity中对viewModel变量赋值,当viewModel的属性值变化时会直接影响UI变化

    val binding: xxxxActivityBinding =
                DataBindingUtil.setContentView(this, R.layout.xxx_layout)
    binding.viewmodel = viewModel
    

    @BindingAdapter

    使用@BindingAdapter修饰一个静态方法,把使用指定属性表达式的值与该方法建立绑定关系
    定义如下方法

    /**
     * Unused Binding Adapter to replace the Binding Converter that hides a view if the number
     * of likes is zero.
     */
    @BindingAdapter("app:hideIfZero")
    fun hideIfZero(view: View, number: Int) {
        view.visibility = if (number == 0) View.GONE else View.VISIBLE
    }
    

    以上方法为View添加了一个xml属性app:hideIfZero,接受一个int参数值。当number值为0时,设置View的visibility为GONE
    使用如下

    <ProgressBar
                android:id="@+id/progressBar"
                app:hideIfZero="@{viewmodel.likes}"
    

    多参数值BindingAdapter方法

    /**
     *  Sets the value of the progress bar so that 5 likes will fill it up.
     *
     *  Showcases Binding Adapters with multiple attributes. Note that this adapter is called
     *  whenever any of the attribute changes.
     */
    @BindingAdapter(value = ["app:progressScaled", "android:max"], requireAll = true)
    fun setProgress(progressBar: ProgressBar, scaled: Int, max: Int) {
        progressBar.progress = (scaled * max / 5).coerceAtMost(max)
    }
    

    为ProgressBar添加一个绑定方法,当同时具有app:progressScaled,android:max属性,并且其值皆为 @{} 表达式时,将关联到此方法;
    requireAll为true表示要求所有属性都存在
    如果为false,则未定义的熟悉值会以null,0等默认值出现

    <ProgressBar
                android:id="@+id/progressBar"
                android:max="@{100}"
                app:progressScaled="@{viewmodel.likes}"
                app:hideIfZero="@{viewmodel.likes}"
    

    @BindingMethods

    让一个参数接受一个 layout expressions 作为参数值,可以用 BindingAdapter实现同样的功能

    /**
     * `app:srcCompat` is an attribute used by the support library to integrate vector drawables. This
     * BindingMethod binds the attribute to the setImageDrawable method in the ImageView class.
     *
     * Binding methods have to be applied to any class in your project. Even an empty one.
     *
     * This is equivalent to:
     * ```
     *
     *   @BindingAdapter("app:srcCompat")
     *   @JvmStatic fun srcCompat(view: ImageView, @DrawableRes drawableId: Int) {
     *       view.setImageResource(drawable)
     *   }
     * ```
     */
    @BindingMethods(
            BindingMethod(type = ImageView::class,
                    attribute = "app:srcCompat",
                    method = "setImageResource"))
    class MyBindingMethods
    

    @BindingConversion

    自动转换 layout expressions 结果值为属性需要的类型值。
    以下实现是把布尔值转换为int值。

    /**
     * The number of likes is an integer and the visibility attribute takes an integer
     * (VISIBLE, GONE and INVISIBLE are 0, 4 and 8 respectively), so we use this converter.
     *
     * There is no need to specify that this converter should be used. [BindingConversion]s are
     * applied automatically.
     */
    object BindingConverters{
    
        @BindingConversion
        @JvmStatic fun booleanToVisibility(isNotVisible: Boolean): Int {
            return if (isNotVisible) View.GONE else View.VISIBLE
        }
    }
    

    有了上面的定义之后,可以在xml中如下使用,整个过程完整自动,不需要任何引入

    <TextView>
        android:visibility="@{false}"
    </TextView>
    

    事件处理

    待更新

    相关文章

      网友评论

        本文标题:Data Binding 笔记(一)

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