android 数据绑定(2)绑定表达式
1.官方文档
https://developer.android.com/topic/libraries/data-binding/expressions.html
2.绑定表达式的约束
2.1 允许的运算符
符号运算符 | + - | |
括号运算符 | () | |
成员访问运算符 | obj.成员 | array[indx] |
类型运算符 | instanceof | 类型强转运算符,如(int)data.pi |
算数运算符 | + - / * % | 包括字符串的+ ,如 '@{"image_" + id}' |
位运算符 | & | ^ ! ~ >> >>> << | |
关系运算符 | == > < >= <= | 其中的 < 要用 xml 转移字符 < |
逻辑运算符 |
|
&要用 & |
三目运算符 |
|
|
非空选择运算符 |
|
??左边非空就返回左边,否则返回右边,如 |
方法调用 | 如 StringUtil.add(1,2) | |
字符串连接运算符 + |
如 "a" + "b" |
2.2 关键字
允许出现 :字符、字符串、数字、null
不允许:new、super、this、泛型调用
2.3 允许函数调用以及lamda表达式
如:
android:text="@{String.valueOf(index + 1)}"
android:onClick="@{() -> presenter.onSaveClick(task)}"
2.4 允许使用集合
声明:
1 <data> 2 <import type="android.util.SparseArray"/> 3 <import type="java.util.Map"/> 4 <import type="java.util.List"/> 5 <variable name="list" type="List<String>"/> 6 <variable name="sparse" type="SparseArray<String>"/> 7 <variable name="map" type="Map<String, String>"/> 8 <variable name="index" type="int"/> 9 <variable name="key" type="String"/> 10 </data>
使用:
1 … 2 android:text="@{list[index]}" 3 … 4 android:text="@{sparse[index]}" 5 … 6 android:text="@{map[key]}"
2.5 允许字符常量
两种方式:
单引号内使用双引号
android:text='@{map["firstName"]}'
或者双引号内使用单引号
android:text="@{map[`firstName`]}"
2.6 允许使用资源
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
2.7 import类型
1 <data> 2 <import type="com.example.User"/> 3 <import type="com.example.MyStringUtils"/> 4 <import type="java.util.List"/> 5 <import type="android.view.View"/> 6 <variable name="user" type="User"/> 7 <variable name="userList" type="List<User>"/> 8 </data>
使用:
1 <TextView 2 android:text="@{MyStringUtils.capitalize(user.lastName)}" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
2.8 类型别名
1 <import type="android.view.View"/> 2 <import type="com.example.real.estate.View" 3 alias="Vista"/>
2.9 Include
1 <?xml version="1.0" encoding="utf-8"?> 2 <layout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:app="http://schemas.android.com/apk/res-auto" 5 xmlns:bind="http://schemas.android.com/apk/res-auto"> 6 <data> 7 <variable name="data" type="com.example.databind.Data" /> 8 <variable name="click" type="com.example.databind.Click" /> 9 </data> 10 <androidx.constraintlayout.widget.ConstraintLayout 11 android:layout_width="match_parent" 12 android:layout_height="match_parent" 13 android:onClick="@{click::onStartClicked}" 14 android:clickable="true"> 15 16 <include 17 android:id="@+id/include" 18 layout="@layout/include" 19 android:layout_width="0dp" 20 android:layout_height="wrap_content" 21 android:layout_marginTop="16dp" 22 app:layout_constraintEnd_toEndOf="@+id/frgmt2" 23 app:layout_constraintStart_toStartOf="@+id/frgmt2" 24 app:layout_constraintTop_toBottomOf="@+id/frgmt2" 25 bind:data="@{data}" /> 26 27 </androidx.constraintlayout.widget.ConstraintLayout> 28 29 </layout>
其中
- xmlns:bind="http://schemas.android.com/apk/res-auto" 声明 bind
- layout指定的布局是一个完整的数据绑定布局文件。
- 数据绑定不支持
<merge> include,如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <layout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:bind="http://schemas.android.com/apk/res-auto"> 4 <data> 5 <variable name="user" type="com.example.User"/> 6 </data> 7 <merge><!-- Doesn't work --> 8 <include layout="@layout/name" bind:user="@{user}"/> 9 </merge> 10 </layout>
3.绑定事件
3.1 两种方法
方法 | 指定事件处理函数 | 绑定事件监听器 |
参数要求 |
参数与返回值必须与listener对应的事件函数一致,如View.OnClickListener(View v) |
可任意参数,返回值要与对应事件处理函数一致。 |
listener创建时机 |
指定的方法不为空时,才创建。 |
绑定数据对象时就创建,始终存在。 |
3.2 指定处理函数示例
第一步:定义处理事件的方法,它的参数要与对应的listener一样
1 public class Click { 2 public void onBackGroundClicked(View view){ 3 4 } 5 }
第二步:在layout定义指定处理事件的方法
1 <?xml version="1.0" encoding="utf-8"?> 2 <layout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:app="http://schemas.android.com/apk/res-auto"> 5 <data> 6 <variable name="data" type="com.example.databind.Data" /> 7 <variable name="click" type="com.example.databind.Click" /> 8 </data> 9 <androidx.constraintlayout.widget.ConstraintLayout 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:onClick="@{click::onStartClicked}" 13 android:clickable="true"> 14 ... 15 16 </androidx.constraintlayout.widget.ConstraintLayout> 17 18 </layout>
第三步:关联方法
1 private FrgmtMainBinding binding; 2 3 private void init(View view){ 4 binding = DataBindingUtil.bind(view); 5 6 MainActivity main = (MainActivity) getActivity(); 7 8 binding.setData(main.data); 9 binding.setClick(new Click()); 10 }
3.2 绑定事件监听器示例
监听器代码:
1 public class Click { 2 public void onResetClicked(Data data){ 3 data.key = "time"; 4 data.value = 10; 5 } 6 }
在layout中绑定:
1 <?xml version="1.0" encoding="utf-8"?> 2 <layout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:app="http://schemas.android.com/apk/res-auto"> 5 <data> 6 <variable name="data" type="com.example.databind.Data" /> 7 <variable name="click" type="com.example.databind.Click" /> 8 </data> 9 <androidx.constraintlayout.widget.ConstraintLayout 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:onClick="@{click::onStartClicked}" 13 android:clickable="true"> 14 15 <Button 16 android:id="@+id/reset" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:layout_marginStart="16dp" 20 android:layout_marginLeft="16dp" 21 android:text="reset" 22 android:onClick="@{() -> click.onResetClicked(data)}" 23 android:textAllCaps="false" 24 app:layout_constraintBottom_toBottomOf="@+id/start" 25 app:layout_constraintEnd_toEndOf="parent" 26 app:layout_constraintStart_toEndOf="@+id/stop" 27 app:layout_constraintTop_toTopOf="@+id/start" 28 app:layout_constraintVertical_bias="1.0" /> 29 30 31 </androidx.constraintlayout.widget.ConstraintLayout> 32 33 </layout>
其中:
第22行的是lamda表达式,也可以把指定参数。
android:onClick="@{(view) -> click.onResetClicked(data)}"