上篇我们知道了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&lt;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&lt;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 &lt; 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&lt;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语法解析(二)的更多相关文章

  1. Android Data Binding代码实践(告别findViewById)(四)

    Data Binding实战(一) Data Binding语法解析(二) Data Binding高级用法(三) 好了,继前三篇学习了Data Binding之后,我们可以发现它的强大之处有这么几点 ...

  2. Android Data Binding Library

    Data Binding Library Data Binding Library是一个支持库,允许您使用声明格式(而不是编程)将布局中的UI组件与应用程序中的数据源绑定. 布局通常在调用UI框架方法 ...

  3. android data binding jetpack VII @BindingAdapter

    android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...

  4. android data binding jetpack I 环境配置 model-view 简单绑定

    android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...

  5. Android Data Binding实战(一)

    在今年Google I/O大会上,Google推出Design Library库的同时也推出了Android Data Binding,那么什么是Data Binding?其名曰数据绑定,使用它我们可 ...

  6. Android Data Binding

    Android官方数据绑定框架DataBinding, 1.什么是DataBinding 2.DataBinding基础用法 3.DataBinding原理 4.表达式 5.null检查 6.incl ...

  7. Android Data Binding(数据绑定)用户指南

    Android Data Binding(数据绑定)用户指南 http://www.jianshu.com/p/b1df61a4df77 https://github.com/LyndonChin/M ...

  8. android data binding jetpack VIII BindingConversion

    android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...

  9. android data binding jetpack VI 清理一些概念。BR 运算表达式

    android data binding jetpack VIII BindingConversion android data binding jetpack VII @BindingAdapter ...

随机推荐

  1. 操作系统服务:OS模块

    http://blog.csdn.net/pipisorry/article/details/52454486 一般的操作系统服务之OS模块Generic Operating System Servi ...

  2. Java程序员必须掌握的线程知识-Callable和Future

    Callable和Future出现的原因 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需 ...

  3. Android插件化的思考——仿QQ一键换肤,思考比实现更重要!

    Android插件化的思考--仿QQ一键换肤,思考比实现更重要! 今天群友希望写一个关于插件的Blog,思来想去,插件也不是很懂,只是用大致的思路看看能不能模拟一个,思路还是比较重要的,如果你有兴趣的 ...

  4. 如何将Provisioning Profile安装到开发的Mac系统上

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...

  5. Java并发框架——AQS阻塞队列管理(一)——自旋锁

    我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这种队 ...

  6. iOS中 CoreGraphics快速绘图(详解) 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 第一步:先科普一下基础知识: Core Graphics是基于C的API,可以用于一切绘图操作 Core Graph ...

  7. J2EE学习从菜鸟变大鸟之六 EJB(Enterprise JavaBean)企业级Java组件

    EJB (EnterpriseJavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准.其特点包括网络服务支持和核心开发工具(SDK).其称为Java 企业Bean,是 ...

  8. Dynamics CRM Microsoft SQL Server 指定的数据库具有更高的版本

    在做NLB部署时遇到这么个问题,CRMAPP1安装的CRM版本是6.1已经打了SP1补丁,而在CRMAPP2上的CRM安装包是6.0版本,在选择连接现有部署后,最后一步检测就出了问题,如下图所示. 看 ...

  9. SVM及其c++代码运用实例

    最近做个小东西,要用到SVM,搜索网上,发现大伙都是各种介绍理论,让我等小码农晕头转向,是故自己学习总结一下,并将代码实例展示出来,方便大家共同探讨,该代码是用opencv编写的,很容易学习滴. 1. ...

  10. UNIX环境高级编程——进程间通讯方法整理

    一.无名管道pipe #include <unistd.h> int pipe(int fd [2]) 二.fifo #include <sys/stat.h> int mkf ...