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. 大数据学习——spark笔记

    变量的定义 val a: Int = 1 var b = 2 方法和函数 区别:函数可以作为参数传递给方法 方法: def test(arg: Int): Int=>Int ={ 方法体 } v ...

  2. day05_01 鸡汤+内容回顾

    推荐电影: 1.被解救的姜戈 2.华尔街之狼 3.阿甘正传 4.辛德勒的名单 5.肖申克的救赎 6.上帝之城 7.焦土之城 8.绝美之城 打印多行 msg = "hello 1 hello ...

  3. 【LeetCode】Binary Tree Preorder Traversal(二叉树的前序遍历)

    这道题是LeetCode里的第144道题. 题目要求: 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很 ...

  4. python装饰器实现用户密码认证(简单初形)

    import timecurrent_user={'user':None}def auth(engine = 'file'): def deco(func): #func=最初始的index和最初始的 ...

  5. iOS开发中六种手势识别

    iOS开发中手势识别有六种: 轻击手势(TapGestureRecognizer), 轻扫手势 (SwipeGestureRecognizer), 长按手势(LongPressGestureRecog ...

  6. 【Luogu】P3574FAR_FarmCraft(树形贪心)

    题解链接 想了一个错的贪心爆零了,气死. 题目链接 #include<cstdio> #include<cctype> #include<cstring> #inc ...

  7. python 缺少包

    https://pypi.python.org/pypi/pdfminer/20140328 到这里下载相应的包,再进行安装. tar  –xivf  pybloomfilter-1.0 cd  py ...

  8. [转] Makefile 基础 (1) —— Makefile 介绍

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

  9. touch event 存疑

    1.原声js与借用jquery输出来的事件列表却不一样 function touchPlay(e) { e.preventDefault(); console.log(e); } var screen ...

  10. 巧克力(zoj 1363)

    2100年,ACM牌巧克力将风靡全球. “绿的,橘红的,棕色的,红的…”,彩色的糖衣可能是ACM巧克力最吸引人的地方.你一共见过多少种颜色?现在,据说ACM公司从一个24种颜色的调色板中选择颜色来装饰 ...