android引入MVVM框架时间还不长,眼下还非常少有应用到app中的。但它是比較新的技术,使用它来搭建项目能省非常多代码,并且能使用代码架构比較清晰。本篇文章是我在学习MVVM时翻译的。篇幅比較长。先翻译前半部分。

这篇文档解析怎样使用数据绑定库来写响应式布局并降低用来绑定应用程序和布局之间冗余代码,使用逻辑层和布局分离。

数据绑定库提供了即灵活又全面的兼容性——它的支持库.so能够用在android2.1平台(API level 7+)。

使用MVVM须要Gradle1.5.0-alphal或更高版本号的插件。

一、測试版

请注意,数据绑定库是一个測试版。尽管数据绑定是处于測试阶段,开发者应该注意下面事项:

*眼下它仅仅是一个測试版。可能不适合你的用例。我们须要你的反馈。

*数据绑定库測试版有重大的改变,包含那些没有源码与应用程序不兼容,也就是说,可能以后须要进行更改。

*开发者应该随时公布应用程序构建与数据绑定库測试版,它与Android SDK和谷歌的服务条款适用,建议常常採用新库或工具来彻底測试自己的应用程序。

二、搭建好开发环境

首先你须要在Android SDK manager中下载支持库。

配置您的应用程序。在你的module中的build.gradle文件里加入dataBinding元素。

使用以下的代码片段来配置数据绑定:

android {
    ....
    dataBinding {
        enabled = true
    }
}

假设你的app使用到的库使用到数据绑定,那你的app也须要在build.gradle文件里进行配置。

另外,确保您正在使用一个兼容的版本号的Android工作室。Android Studio 1.3或更新的版本号支持数据绑定。

数据绑定的布局文件

编写你的第一个数据绑定布局

数据绑定布局文件略有不同,它以layout作为布局的起点,,后跟一个data标签和一个view元素。

这个view元素是普通不使用数据绑定布局的根元素。一个演示样例文件是这种:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.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.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>

data中使用的variable表示了一个可能会在这个布局中作用的属性。

<variable name="user" type="com.example.User"/>

布局属性的设置使用“@ { }”语法,这里TextView的文字属性就设置为user中的firstName属性。

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{user.firstName}"/>

对象

让我们如果如今有一个User的普通java对象(POJO):

public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}

这样的类型的对象数据不会改变。

通常在应用程序的数据读取一次,永远不会改变。它还能够改为javabean对象:

public class User {
private final String firstName;
private final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}

从数据绑定的角度来看,这两个类是等价的。用于设置TextView的android:文本的表达式@{user.firstName}将訪问第一个类中的firstName字段和后一个类的getFirstName()方法。另外,假设firstName()方法存在。它还将訪问firstName()方法。

绑定数据

默认情况下,绑定类的名称是基于布局文件的名称起的,它是将布局文件名称开头大写并加上“Binding”而成。上述布局文件名称称为main_activity.xml。那它的绑定类名为MainActivityBinding。这个类拥有全部从属性(比如用户变量)到布局的绑定关系并知道怎样赋值绑定表达式。最简单的方法创建绑定的方法就是通过反射:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);
}

完毕了!执行应用程序,你会看到在UI上看到“Test User”。另外,你也能够通过下面代码来获取view:

MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());

假设你想在 ListView或者RecyclerView 使用数据绑定。你应该这样使用:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

绑定事件

事件能够直接绑定到处理程序方法,类似于android:onClick能够分配给一个Activity的方法。事件属性名称是listener方法的名称有一部分。

比如,View.OnLongClickListener有一个onLongClick()方法,所以这个事件的属性名应写为android:onLongClick。

分配一个事件给handler。用法名称来作为正常绑定表达式的变量,比如,假设您的数据对象有两个方法:

public class MyHandlers {
public void onClickFriend(View view) { ... }
public void onClickEnemy(View view) { ... }
}

绑定表达式会为View 分配一个click监听事件。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.Handlers"/>
<variable name="user" type="com.example.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.firstName}"
android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"
android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
</LinearLayout>
</layout>

三、布局细节

Imports

零个或多个导入元素能够使用内部数据元素。

这些同意简单引用类内部布局文件,就像在Java。

<data>
<import type="android.view.View"/>
</data>

如今,view能够使用在你的绑定表达式:

<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>

当有类名称冲突,当中一个类可能用alias进行重命名:

<import type="android.view.View"/>
<import type="com.example.real.estate.View"
alias="Vista"/>

如今,Vista能够使用 com.example.real.estate.view中的引用而且View可用于代表android.view.view。导入类型能够在变量和表达式中作为类型引用:

<data>
<import type="com.example.User"/>
<import type="java.util.List"/>
<variable name="user" type="User"/>
<variable name="userList" type="List<User>"/>
</data>

注意:Android studio还没处理好import的自己主动导入,因此你的IDE可能无法自己主动导入变量,你能够在变量定义使用全然限定名称。这样你的应用程序仍能够正常编译。

<TextView
android:text="@{((User)(user.connection)).lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

导入类型时也能够使用在引用静态字段和方法中:

<data>
<import type="com.example.MyStringUtils"/>
<variable name="user" type="com.example.User"/>
</data>

<TextView
android:text="@{MyStringUtils.capitalize(user.lastName)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

就像在java中,java.lang.*会自己主动导入一样。

变量

数据元素能够使用随意数量的变量元素。

每一个变量元素描写叙述一个属性,它都必须在layout中通过绑定表达式来设置值。

<data>
<import type="android.graphics.drawable.Drawable"/>
<variable name="user" type="com.example.User"/>
<variable name="image" type="Drawable"/>
<variable name="note" type="String"/>
</data>

变量在编译时进行类型检查,假设一个变量实现了Observable接口或者它是一个observable集合,那应该反射得到。假设变量是一个没有实现Observable的基类或接口。,那变量将无法被观察到!

当不同的布局文件里的变量配置不同样(如landscape或者protrait),这些变量将被组合起来。

在这些布局文件之间定义变量不会有冲突。

生成的绑定类中,相应每一个变量都有一个setter和getter方法。变量将设置为默认的Java值直到setter被调用,如引用类型默觉得null,int默认值是0,boolean默觉得false等。

Custom Binding Class Names

默认情况下,生成绑定类名称是基于布局文件的名称的,把布局文件名开头用大写,删除下划线(_),最后加上”Binding”。

这个类将被放置在module的一个databinding包模块下。比如。contact_item.xml将产生一个类名ContactItemBinding的类。假设module包名为com.example.my。那么它将会被放置在com.example.my.app.databinding这个包下。

通过调整数据元素的class属性能够将绑定类重命名或放置在不同的包。比如:

<data class="ContactItem">
...
</data>

这个生成绑定类ContactItem将会存在module包下的databinding包中。假设想让生成的类存放在module中的还有一个包下,它增加前缀”.”:

<data class=".ContactItem">
...
</data>

这样的情况下。ContactItem将被直接放置在module包下。假设想放在其他包能够使用包名的全称:

<data class="com.example.ContactItem">
...
</data>

Includes

变量能够通过一个included元素导入到布局文件里。included中要有应用程序名称空间和属性的变量名:
?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.example.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变量。

数据绑定不支持直接在merge元素里加入include并以此来作为子view,
<pre name="code" class="html"><span style="font-weight: normal;"><?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.example.User"/>
</data>
<merge>
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</merge>
</layout></span>

表达式语法

共同特性

表达式语法跟java语法非常像,以下的一样的语法:

· 数学计算 + - / * %

· 字符串连接 +

· 逻辑运算符&& ||

· 位运算& | ^

· 一元运算 + - ! ~

· 位移>> >>> <<

· 比較== > < >= <=

· instanceof

· Grouping ()

· 文字 - character, String, numeric, null

· Cast

· 方法调用

· 字段訪问

· 数组訪问 [ ]

· 三元运算符?

:

比如:

android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'

不具备的方法

有一些操作仅仅能在Java表达式中使用。

· this

· super

· new

· Explicit generic invocation

空联合操作

联合操作符(?

?)不为空的话选择左边操作,为空的话选择右边操作。

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

它等同于:

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

避免指针异常

生成数据绑定代码会自己主动检查null,避免空指针异常。比如,在表达式@ { user.name },假设用户是null,user.name分配其默认值(null)。

假设是@ { user.age }。

age是int,那么它将默认值为0。

Collections

集合共同点:数组,list,sparse list和map,为了方便訪问。均能够使用[ ]操作符。

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

文字字符串

使用单引號包裹住属性值,这样就非常easy在表达式中使用双引號:

android:text='@{map["firstName"]}'

还能够使用双引號包围的属性值。当这样做时,字符串应该使用"或引號(`)。

android:text="@{map[`firstName`}"
android:text="@{map["firstName"]}"

资源文件

能够使用正常的訪问资源的表达式语法:

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

格式字符串和复数能够通过提供參数来定义:

android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"

当一个复数多个參数。全部參数都应该通过:

Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"

一些资源须要显式类型的评估:.

Type

Normal Reference

Expression Reference

String[]

@array

@stringArray

int[]

@array

@intArray

TypedArray

@array

@typedArray

Animator

@animator

@animator

StateListAnimator

@animator

@stateListAnimator

color int

@color

@color

ColorStateList

@color

@colorStateList

Data Binding Guide——google官方文档翻译(上)的更多相关文章

  1. Data Binding Guide——google官方文档翻译(下)

    这篇博客是Data Binding Guide官网文档翻译的下篇.假设没看过前半部分翻译的能够先看Data Binding Guide--google官方文档翻译(上)  一,数据对象 不论什么不含业 ...

  2. GreenDao官方文档翻译(上)

    笔记摘要: 上一篇博客简单介绍了SQLite和GreenDao的比较,后来说要详细介绍下GreenDao的使用,这里就贴出本人自己根据官网的文档进行翻译的文章,这里将所有的文档分成上下两部分翻译,只为 ...

  3. 告别findViewById(),ButterKnife,使用Google Data Binding Library(1)

    Data Binding Library 用数据绑定编写声名性布局,可以最大限度的减少findViewById(),setOnClickListener()之类的代码.并且比起findViewById ...

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

    1)介绍 这篇文章介绍了如何使用Data Binding库来写声明的layouts文件,并且用最少的代码来绑定你的app逻辑和layouts文件. Data Binding库不仅灵活而且广泛兼容- 它 ...

  5. 完全掌握Android Data Binding

    转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html 来源 https://github.com/L ...

  6. Data Binding MVVM 数据绑定 总结

    示例代码:https://github.com/baiqiantao/DataBindingTest 参考:精通Android Data Binding    Android Data Binding ...

  7. 精通 Android Data Binding

    转自:https://github.com/LyndonChin/MasteringAndroidDataBinding 官方虽然已经给出了教程 - Data Binding Guide (中文版 - ...

  8. (Android MVVM)使用Data Binding Library(1)

    Data Binding Library 用官方提供的Data Binding Library,可以最大限度的减少findViewById(),setOnClickListener()之类的胶水代码, ...

  9. 从零開始的Android新项目7 - Data Binding入门篇

    Data Binding自从去年的Google I/O公布到至今,也有近一年的时间了.这一年来,从Beta到如今比較完好的版本号.从Android Studio 1.3到如今2.1.2的支持,能够说D ...

随机推荐

  1. 序列化 pickle & json & shelve

    把内存数据转成字符,叫序列化,dump,dumps 把字符转成内存数据类型,叫反序列化load,loads dumps:仅转成字符串 dump不仅能把对象转换成str,还能直接存到文件内 json.d ...

  2. python学习-- Django model -class 主键自增问题

    转自:http://blog.csdn.net/mapoor/article/details/8609660 prize_id = models.IntegerField(primary_key=Tr ...

  3. Django创建并连接数据库(实现增删改查)--ORM框架雏形

    第一步:要先创建数据库(orm是不能创建数据库的) 第二步:settings里面指定连接到哪个数据库 DATABASES = { #默认使用的是sqlite3数据库 'default': { 'ENG ...

  4. AtCoder Grand Contest 020

    A - Move and Win Time limit : 1sec / Memory limit : 512MB Score : 300 points Problem Statement A gam ...

  5. operator的各种问题

    a+b = a^b + (a&b)<<1 用位运算实现两数相加 int Add(int a,int b) { return b?Add(a^b,(a&b)<<1 ...

  6. http.server()的理解

    http.server()相当于实例化一个server,等价于http.createServer(). 以下为个人理解 http.server()为创建一个http服务,http.server()可以 ...

  7. JDBC 学习笔记(八)—— ResultSet

    JDBC 使用 ResultSet 来封装 SQL 的查询结果,可以将 ResultSet 类比为数据库表的查询结果. 它拥有如下两个性质: 可滚动. 可更新. 这两个性质,是在创建 Statemen ...

  8. 【bzoj2819】Nim DFS序+树状数组+倍增LCA

    题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  9. hdoj--1010<dfs+奇偶剪枝>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目描述:在n*m的矩阵中,有一起点和终点,中间有墙,给出起点终点和墙,并给出步数,在该步数情况 ...

  10. android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析

    android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析 导语: 笔者主要研究方向是网络通信协议的加密解密, 对应用程序加固脱壳技术很少研究, 脱壳壳经历更是经历少之甚少. ...