跳至主要內容

04.Databinding布局和绑定表达式


Android开发Jetpack-Databinding布局和绑定表达式

在布局中,我们可以通过@{}来绑定我们的控件与数据,我们看看在这个坑里我们可以做些什么东西呢?

常用运算符

在这里面,可以使用多种表达式,比如说:

官方文档:grouping、cast这些不用管,知道是分组、强转就行了,官方文档也是狗屎一样,也没有详细的说明。知道常用的基本上满足我们的日常开发了。

  • Mathematical + - / * %
  • String concatenation +
  • Logical && ||
  • Binary & | ^
  • Unary + - ! ~
  • Shift >> >>> <<
  • Comparison == > < >= <= (Note that < needs to be escaped as <)
  • instanceof
  • Grouping ()
  • Literals - character, String, numeric, null
  • Cast
  • Method calls
  • Field access
  • Array access []
  • Ternary operator ?:
  • 算术运算符 + - / * %
  • 字符串连接 +
  • 逻辑 && ||
  • 二元 & | ^
  • 一元 + - ! ~
  • 移位运算符 >> >>> <<
  • 比较运算符 == > < >= <=
  • Instanceof
  • Grouping ()
  • 文字 - character, String, numeric, null
  • Cast
  • 方法调用
  • Field 访问字段
  • Array 访问数组
  • 三元运算符 ?:

判空null

官方例子:

android:text="@{user.displayName ?? user.lastName}"

如果左边为null,那么会显示右边的内容

等价于这一行代码

android:text="@{user.displayName != null ? user.displayName : user.lastName}"

获取对象属性

比如前面我们代码显示用户的名称

我们直接写:

<TextView
    android:id="@+id/textView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.name}"
    app:layout_constraintBottom_toTopOf="@+id/guideline"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="@+id/guideline4"
    app:layout_constraintTop_toTopOf="parent" />

android:text="@{user.name}" 这里面访问对象的属性,就类似于我们的getter方法

避免空指针异常

databinding会自动地检查null,避免控制真异常。如果是为null的话则会显示默认值。

比如说前面的user.name,如果user为null,那么这个name是字符串类型,会显示null,如果前面的user.age,如果user为null,那么age是int类型,会显示默认值0

其他控件引用

比如说你在你的布局里有一个EditText,它的id为input_box,你还有一个TextView,如果它要显示EditText的内容,可以这么做

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.3" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.1" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.2" />

        <TextView
            android:id="@+id/textView9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text_account"
            app:layout_constraintBottom_toTopOf="@+id/guideline6"
            app:layout_constraintEnd_toStartOf="@+id/guideline5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView10"
            android:text="@{inputBox.text}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="@+id/guideline7"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline5"
            app:layout_constraintTop_toTopOf="@+id/guideline6" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:id="@+id/input_box"
            android:hint="请输入用户名"
            android:inputType="textPersonName"
            app:layout_constraintBottom_toTopOf="@+id/guideline6"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline5"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
图片描述
图片描述

这里面注意一下名字,ID用下划线隔开,然后使用的是驼峰命名。

集合数据

这种情况一般不用,知道就行。因为我们集合的话一般对应着列表,列表的话我们会集合适配器来渲染,后面我们再用例子来说明一下吧。

官方的文档:

<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]}"

接下来我们用一个例子来说说明一下吧

布局代码

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="java.util.List" />

        <import type="java.util.Map" />

        <variable
            name="userList"
            type="List&lt;String>" />

        <variable
            name="scoreMap"
            type="Map&lt;String,Integer>" />

        <variable
            name="index"
            type="int" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"username is : "+userList[index]}'
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.101" />

        <TextView
            android:id="@+id/textView8"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"score is : "+String.valueOf(scoreMap[userList[index]])}'
            android:textColor="#000"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.198" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

CollectionActivity.kt代码

class CollectionActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val collectionBinding: ActivityCollectionBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_collection)
        //List集合
        collectionBinding.userList = listOf("TrillGates")
        //Map集合
        collectionBinding.scoreMap = hashMapOf("TrillGates" to 100)
        //index
        collectionBinding.index = 0
    }

}
图片描述
图片描述

资源引用

也就是我们的表达式里也可以引用资源内容

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="user"
            type="com.sunofbeaches.databindingdemo.domain.User" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:textColor="@{@color/colorAccent}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{@string/app_name}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{@string/text_user_info(user.name,user.age)}" />
    </LinearLayout>
</layout>

ResourceActivity.kt的代码

class ResourcesActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val resourcesBinding = DataBindingUtil.setContentView<ActivityResourcesBinding>(
            this,
            R.layout.activity_resources
        )
        resourcesBinding.user = User("拉大锯", 30, Gender.MALE)
    }
}

运行效果

图片描述
图片描述

某些资源需要特定的类型,请参考下图

图片描述
图片描述