2016android新技术之DataBinding

Anroid数据绑定框架DataBinding,堪称解决界面逻辑的黑科技

原文链接:http://www.jianshu.com/p/2d3227d9707d    
去年谷歌 I/O大会上介绍了一个非常厉害的新框架DataBinding, 数据绑定框架给我们带来了很大的方便,以前我们可能需要在每个Activity里写很多的findViewById,不仅麻烦,还增加了代码的耦合性,如果我们使用DataBinding,就可以抛弃那么多的findViewById,省时省力。说到这里,其实网上也有很多快速的注解框架,但是注解框架与DataBinding想比还是不好用,而且官网文档说DataBinding还能提高解析XML的速度,其实DataBinding的好用,不仅仅体现在可以省去使用很多啰嗦findViewById。(看到这里是不是有点小激动呢,lz看到这里也是异常的激动呢)还有很多。往下看你就会明白的。
在介绍DataBinding之前,肯定是要先学会搭建使用它的环境。鉴于是去年发布的,现在大家AS的版本估计都是在1.5版本以上了(lz转载这个博客时使用的是2.2),就在1.5版本上搭建和介绍吧,1.5之前大家可以在网上搜索,因为我看网上大多数是介绍的1.3的使用方法,还没有很多对于1.5之后环境搭建的方法。(废话说这里接下来进入正题 吐舌头)。

环境搭建:

Android的Gradle插件版本不低于1.5.0-alpha1;
classpath'com.android.tools.build:gradle:1.5.0'
然后修改对应模块(Module)的build.grade:
注意 :Android studio的版本一定要大于1.3,而且Android Studio目前对于binding对象没有自动代码提示,只会在编译时进行检查。1.3及以前的版本对于环境的搭建,可能有点麻烦。(1.3环境搭建方法,网上多的是)

基础展示:

我们在具体讲解之前,先用一个简单的小列子来学习一下基础并展示DataBinding的巨大魅力,估计就会被其简单的特性所吸引哦。
package cn.edu.niit.test_databinding;

/**
 * Created by zhdk on 2016/10/20.
 */

public class User {
    private String name;
    private String age;

    public User(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
 
其次,来看下使用了DataBinding之后的布局文件是什么样子的呢?主要的变化是在layout布局文件之中(注意了:这里就是魅力所在 大笑)。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="user"
            type="cn.edu.niit.test_databinding.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

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

</layout>
看到这里,可能有的人就开始有点迷糊了,没有给控件定义id,而是用了@{}方法,到底是怎么回事?先不忙,一会再来一一解释,
我们再来看看怎么把值传进去的,在Activity中是怎样使用的。
package cn.edu.niit.test_databinding;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import cn.edu.niit.test_databinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        User user = new User("zhdk", "21");
        binding.setUser(user);
    }
}
看到这里是不是感觉Activity里面的代码很简洁,很清爽,没有了初始化fingdViewById,然后再去setText(),就仅仅添加了
两行代码。
运行结果肯定也不用说了:

基础解释:

布局生命

列子我们介绍完了,对于列子中出现的一些新东西,有必要解释一下,java bean那里就不解释了,只要是有点基础的朋友应该都懂,我们就从布局文件讲起。相比以前的xml,根节点由具体的某个layout(比如LinearLayout变成了layout),里面包括了data节点和传统的视图。这里的data节点就像是链接view和modle的桥梁。在这个data节点中声明一个variable变量,那值就可以轻松的传到布局文件来了。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
	<!--type声明的就是我们用户实体类User,一定要写全,带着包名-->
    <data>

        <variable
            name="user"
            type="cn.edu.niit.test_databinding.User" />
    </data>
	........
</layout>
TextView中的@{user.name}就是把这个user中的名字展示出来,age同样如此。

绑定variable

虽然在布局文件中对应上了,但是值是怎么传进去的呢?这就是我们要讲的Activity中的两行代码了,它把实体类和布局文件进行了绑定。修改MainActivity中的onCreate,用DataBindingUtil.setContentView();来代替setContentView();然后创建一个user对象,通过binding.setUser(user);与variable进行绑定。

高级用法

import用法:

其实data节点也是支持import用法的,比如:
<data>
    <import type="cn.edu.niit.test_databinding.User" />
    <variable
        name="user"
        type="User" />
</data>
这里需要注意的是:import并不能像java一样可以 import xx.xxx.*,必须具体写清楚要导入的类名。

类名相同

到这里你可能会问如果import了两个相同名称的类咋办?别怕,人家想的很周到,可以起个别名或者昵称的:

<data>

    <import
        alias="MyUser"
        type="cn.edu.niit.test_databinding.User" />
    <import type="cn.edu.niit.detal.test_databinding.User" />

    <variable
        name="user"
        type="User" />

    <variable
        name="myUser"
        type="MyUser" />
</data>

变量定义高级用法

在上面,我们学会了如何在xml中定义一些简单的变量。我们没有定义像List、Map等这样的集合变量。那这种集合变量该如何定义呢?其实定义的方式和我们上面的基本一致,区别就在于我们还需要为它定义key的变量,例如:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="java.util.ArrayList" />

        <import type="java.lang.String" />

        <variable
            name="list"
            type="ArrayList&lt;String>" />
        <!--泛型的支持会在编译时期报红线,但是是可以直接运行的
        但是需要通过转义字符才行,如:&lt;数据类型> 或者&lt;数据类型&gt;-->

        <import type="java.util.Map" />

        <variable
            name="map"
            type="Map&lt;String,String&gt;" />

        <variable
            name="arrays"
            type="String[]" />
    </data>
    <!--我们需要展示的布局-->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{list[0]}" />
        <!--List集合既可以和数组一样通过索引获取值list[index]方式,也可以调用API-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{list.get(1)}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{map[`name`]}" />
        <!--Map集合既可以通过map[key]的方式,也可以通过调用API-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{map.get(`age`)}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{arrays[0]}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:text="@{arrays[1]}" />

    </LinearLayout>
</layout>
注意:泛型的支持会在编译时报红线,但是是可以直接运行的,但是需要通过转义字符才行。



Activity中的代码:

package cn.edu.niit.test_databinding;

import android.databinding.DataBindingUtil;
import android.databinding.tool.CompilerChef;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import cn.edu.niit.test_databinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        ArrayList<String> list = new ArrayList<>();
        list.add("first");
        list.add("second");
        binding.setList(list);

        Map<String, String> map = new HashMap<>();
        map.put("name", "zhangsan");
        map.put("age", "40");
        binding.setMap(map);

        String[] arrays = {"lisi", "laowang"};
        binding.setArrays(arrays);
    }
}
关于UI上的操作全部放在xml文件里面,是不是感觉方便了许多了呢?

布局引用文件(includes):

变量可以传递到布局文件引用的布局文件中
<? 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 >

事件绑定:

如果对控件进行点击事件处理,只需在<data>标签里面添加<variable>然后设置自己的点击事件,type类型指定为:android.view.View.OnClickListener,具体实现如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="myClick"
            type="android.view.View.OnClickListener" />
    </data>

    <Button
	android:id="@+id/btn1"
android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{myClick}" android:text="点击" /></layout>

在代码中实现点击事件:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainBinding binding = DataBindingUtil.setContentView(this, R.layout.main);
        binding.setMyClick(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //要做的事
            }
        });
    }
也可以通过id来实现绑定:
binding.btn1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

    }
});

表达式:

在xml中也是支持表达式的:
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text='@{error ? "error" : "ok"}'/>

这是一个布尔值的使用。
下面我们就来看看表达式支持的一下语法和不支持的语法
支持的表达式:
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:

不支持的表达式:
this
super
new
Explicit generic invocation


ok,关于DataBinding的基础部分差不多也就这样了,当然,还有很多高级的用法,大家可以查阅更多的资料去学习。



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值