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<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<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<String>" />
<variable
name="scoreMap"
type="Map<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)
}
}
运行效果
某些资源需要特定的类型,请参考下图