Android Data Binding语法解析(二)
上篇我们知道了Data Binding的最简单的用法,那么Data Binding其中最为重要也是最复杂的其实就是在xml布局文件中给对应的控件进行数据绑定了,接下来就一一说明Data Binding的使用各个场景的语法。
我们以User类这个Model为例:
public class User {
private String userName;
private String userPassword;
private boolean isExist;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public boolean isExist() {
return isExist;
}
public void setIsExist(boolean isExist) {
this.isExist = isExist;
}
public User(String userName, String userPassword, boolean isExist) {
this.userName = userName;
this.userPassword = userPassword;
this.isExist = isExist;
}
}
Imports
就像Java代码一样,我们可以使用import导入我们在xml文件绑定数据时需要使用到的类,如我们需要使用到系统中的View类,可以这样:
<data>
<import type="android.view.View"/>
</data>
然后使用它对控件进行相应属性值的绑定,如:
<TextView
android:text="@{user.userName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isExist? View.VISIBLE : View.GONE}"/>
这样我们就可以使用View类的一些值,通过@{}来绑定这些值,用三元表达式进而决定控件的可见性。
class name conflicts类名冲突
如果我们自己创建了一个类名也为View,如:
public class View {
private int width;
private int height;
/*
* getter and setter ......
* */
}
很明显这和系统中的View类名一样,那么在xml中怎么区别这两个不同的类呢?就是通过设置别名来区分。如:
<data>
<import type="android.view.View"/>
<import type="com.sunzxyong.databinding.View"
alias="MyView"/>
</data>
我设置了我自己定义的View别名为MyView,那么对控件进行数据绑定时候就使用这个别名,如:
<TextView
android:text="@{MyView.width}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isExist ? View.VISIBLE : View.GONE}"/>
List集合的使用
假如我们有多位用户,我们需要显示第1位用户的数据,那么可以这样:
<data>
<import type="com.sunzxyong.databinding.User"/>
<import type="java.util.List"/>
<variable name="userList" type="List<User>"/>
</data>
这里我们定义了一个List<User> 这样的一个集合,名为userList,其中特别注意一点,在@{}表达式中不支持左括号,所以我们需要用转义字符代替左括号,然后在控件中获取集合的数据是通过userList[0]来获取的,这点和数组一样,而我们定义的是List<User>集合,所以最终获取第一位用户的用户名是这样的:userList[0].userName,然后绑定数据在控件上,表示显示第一位用户的数据代码如下:
<TextView
android:text="@{userList[0].userName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
这里打印出来的将是集合中第一个元素的userName。
如果index索引需要动态改变,那么就这样:
<data>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="index" type="int"/>
</data>
…
android:text="@{list[index]}"
Variables变量
【注意一点】java.lang.*包下的类是不需要导入的,因为这和java一样lang包下的类都是自动导入进去了,如:
<data>
<variable
name="number"
type="String"/>
</data>
绑定数据:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{number}" />
然后通过代码设置mBinding.setNumber(“888888”);那么屏幕上显示将是888888。
因为自动导入了lang包,可以直接使用String、int、boolean等类,这些变量在没有传递值的情况下和java一样,都有默认值,引用类的为null,int为0,boolean为false等。
自定义Binding Class Name,也就是自定义ViewModel类名,不是用系统默认根据xml文件名生成的
我们知道系统默认是根据xml布局文件名来生成Binding Class Name的,如:first_activity.xml,那么生成的Binding Class Name就是FirstActivityBinding,如果该app module的包名为com.sunzxyong.hello,那么生成的Bindind Class Name所处的依赖的包为com.sunzxyong.hello.databinding,在使用时候AS会自动导入该包,如:
import com.sunzxyong.hello.databinding.FirstActivityBinding
那么怎么自定义Binding Class 名呢?就是通过<data class=”“>设置<data>节点中class的名字就是我们自定义的Binding Class 名字,比如我们把Binding Class 名改为MyBinding,则:
<data class="MyBinding">
...
</data>
则该xml的Binding Class Name为MyBinding,代码中获取就变为这样了:
MyBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
而它的默认依赖包名也是在module包下的databinding包中。
当然也可以自己定义Binding Class 的包名:
<data class="com.example.MyBinding">
...
</data>
当布局中包含另外一个子布局时,使用include时数据共享
如:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.sunzxyong.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</LinearLayout>
</layout>
该布局包含了两个另外的子布局分别为name.xml和contact.xml,那么如果想要这两个子布局也共用一个User数据,那么需要在include节点中添加:
bind:user=”@{user}”
然后添加命名空间:
xmlns:bind=”http://schemas.android.com/apk/res-auto”
然后name.xml和contact布局中也需要定义数据绑定:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.sunzxyong.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.userName}" />
</LinearLayout>
</layout>
【注意】:官方文档上说the following layout is not supported <merge>标签:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.sunzxyong.User"/>
</data>
<merge>
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</merge>
</layout>
这是不支持的。
@{}表达式支持的运算
基本上和java的一样:
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:
如:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
不支持的语法:
this
super
new
Null Coalescing 操作符
如果firstName为null,则选择laseName,否则选择firstName:
android:text="@{user.firstName ?? user.lastName}"
它等于:
android:text="@{user.firstName != null ? user.displayName : user.lastName}"
使用Map<Key,Value>集合
<data>
<import type="java.util.Map"/>
<variable name="map" type="Map<String, String>"/>
<variable name="key" type="String"/>
</data>
…
android:text="@{map[key]}"
可以看到map的数据获取也是通过map[]中括号的形式,只不过这里传入的是对应的Key,而List则是传入对应的int类型的索引。
Resources资源的访问
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"
可以看到和平常的访问是一样的,也是通过@访问。
好了,Data Binding的语法的使用就讲完了!下一篇将继续叙述高级的用法。。。
Android Data Binding语法解析(二)的更多相关文章
- Android Data Binding代码实践(告别findViewById)(四)
Data Binding实战(一) Data Binding语法解析(二) Data Binding高级用法(三) 好了,继前三篇学习了Data Binding之后,我们可以发现它的强大之处有这么几点 ...
- Android Data Binding Library
Data Binding Library Data Binding Library是一个支持库,允许您使用声明格式(而不是编程)将布局中的UI组件与应用程序中的数据源绑定. 布局通常在调用UI框架方法 ...
- android data binding jetpack VII @BindingAdapter
android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...
- android data binding jetpack I 环境配置 model-view 简单绑定
android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...
- Android Data Binding实战(一)
在今年Google I/O大会上,Google推出Design Library库的同时也推出了Android Data Binding,那么什么是Data Binding?其名曰数据绑定,使用它我们可 ...
- Android Data Binding
Android官方数据绑定框架DataBinding, 1.什么是DataBinding 2.DataBinding基础用法 3.DataBinding原理 4.表达式 5.null检查 6.incl ...
- Android Data Binding(数据绑定)用户指南
Android Data Binding(数据绑定)用户指南 http://www.jianshu.com/p/b1df61a4df77 https://github.com/LyndonChin/M ...
- android data binding jetpack VIII BindingConversion
android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...
- android data binding jetpack VI 清理一些概念。BR 运算表达式
android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...
随机推荐
- char能表示(-128~127)
char 的取值范围是 -128 ~127 注:数0的补码表示是唯一的: +0的补码=+0的反码=+0的原码=00000000 -0的补码=11111111+1=00000000(mod 2的8次方) ...
- UNIX网络编程——epoll 的accept , read, write(重要)
在一个非阻塞的socket上调用read/write函数,返回EAGAIN或者EWOULDBLOCK(注:EAGAIN就是EWOULDBLOCK). 从字面上看,意思是: EAGAIN: 再试一次 E ...
- win7下创建逻辑分区
许多用户在安装Win7时都遇,安装程序创建的都是主分区,并没有创建逻辑分区的任何选项,这样的情况导致创建4个主分区后剩余的空间无法继续分配的情况,这使得许多用户情何以堪.很多用户都向小编反映该问题,有 ...
- React Native自动化测试
大凡做软件开发,肯定会涉及到很多的测试,本地测试,Junit测试,用例测试等,今天就来说说RN的测试. React Native的官方代码仓库里有一些测试代码,你可以在贡献代码之后回归测试一下,以检测 ...
- 1073. Scientific Notation (20)
题目如下: Scientific notation is the way that scientists easily handle very large numbers or very small ...
- UNIX网络编程——非阻塞式I/O(套接字)
套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类: (1)输入操作,包括read,readv,rec ...
- sql的索引:网上看到不错,整理成自己的东西
数据库建立索引可以提高查询速度.假如我们创建了一个 mytable表: CREATE TABLE mytable(ID INT NOT NULL,username VARCHAR(16) NOT NU ...
- python的subprocess:子程序调用(调用执行其他命令);获取子程序脚本当前路径问题
python当前进程可以调用子进程,子进程可以执行其他命令,如shell,python,java,c... 而调用子进程方法有 os模块 参见:http://blog.csdn.net/longshe ...
- Spring事务管理与数据库隔离级别的关系(Spring+mysql)
之前写过一篇文章<数据库隔离级别(mysql+Spring)与性能分析 >,里面很多问题写的不是很专业,也不是很有逻辑性,现在重新整理一下,希望对大家有帮助. 这部分通过两天时间反复的 ...
- Linux服务器Jboss运行环境搭建步骤和开机自动启动脚本编写运行
Jboss运行环境:Linux+Jdk+Jboss+jsp系统 Jboss软件说明:类似于Tomcat,就是一个跑Jsp系统的环境,他的站点路径跟Tomcat类似,Tomcat存放站点文件到webap ...