数据绑定框架DataBinding--入门篇

一、描述

MVC,MVP都是大家所熟知的,而今天的主题的MVVM数据绑定,这个是最新推出的框架,刚加入公司没多久,看公司里的同事再用这个,所以我熟悉之后发现确实挺好用的,在这里分享给大家。

二、引用

Data Binding自从去年的Google I/O发布到至今,也有近一年的时间了。这一年来,从Beta到如今比较完善的版本,从Android Studio 1.3到如今2.1.2的支持,可以说Data Binding已经是一个可用度较高,也能带来实际生产力提升的技术了。

而事实上,真正使用到Data Binding的公司、项目仍然是比较少的。可能是出于稳定性考虑,亦或是对Data Binding技术本身不够熟悉,又或许对新技术没什么追求。

我司在新的产品中就全面使用了Data Binding技术,无论是我,还是新来直接面对Data Binding上手的工程师也好,都对其爱不释手,用惯了后简直停不下来。

希望在看完本文的介绍后,会有更多的朋友产生兴趣,来使用Data Binding,参与它的讨论。

三、什么是DataBinding

这里我以我的理解来说,就是一个或者多个实体对象对应着一个页面,实体中的某些属性绑定着页面上的控件,当属性的值改变时,页面上的控件会自动更新数据。

四、效果展示

没用DataBinding之前

XML布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.junwen.databinding.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="姓名:" />

        <TextView
            android:id="@+id/activity_main_stu_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="学生姓名" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="年龄:" />

        <TextView
            android:id="@+id/activity_main_stu_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="学生年龄" />
    </LinearLayout>


    <Button
        android:id="@+id/activity_main_stu_setting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更改姓名" />
</LinearLayout>

Student实体类


/**
 * 描述:学生对象
 * 作者:卜俊文
 * 创建:2016/8/10 10:20
 * 邮箱:344176791@qq.com
 */
public class Student {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}



MainActivity主页面



public class MainActivity extends AppCompatActivity {

    private TextView tv_name; //学生姓名
    private TextView tv_age; //学生年龄
    private Button btn_setting; //设置
    private Student student; //学生对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initListener();
    }


    /**
     * 描述:初始化控件
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/10 10:17
     */
    private void initView() {
        tv_name = (TextView) findViewById(R.id.activity_main_stu_name);
        tv_age = (TextView) findViewById(R.id.activity_main_stu_age);
        btn_setting = (Button) findViewById(R.id.activity_main_stu_setting);
    }

    /**
     * 描述:初始化数据
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/10 10:19
     */
    private void initData() {
        //创建一个学生对象
        student = new Student("俊文", 22);
        //根据学生对象赋值到控件上
        tv_name.setText(student.getName());
        tv_age.setText(String.valueOf(student.getAge()));
    }

    /**
     * 描述:初始化监听
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/10 10:22
     */
    private void initListener() {
        btn_setting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //点击设置,更改Student对象的名字。
                student.setName("卜俊文");
                tv_name.setText(student.getName());
            }
        });
    }

}


运用DataBinding

XML布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="student"
            type="com.example.junwen.databinding.Student" />
    </data>

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="姓名:" />

            <TextView
                android:id="@+id/activity_main_stu_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="@{student.name}" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="年龄:" />

            <TextView
                android:id="@+id/activity_main_stu_age"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="@{String.valueOf(student.age)}" />
        </LinearLayout>


        <Button
            android:id="@+id/activity_main_stu_setting"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="更改姓名" />
    </LinearLayout>
</layout>  

Student实体类



/**
 * 描述:学生对象, @Bindable注解是为了能在BR里面找到这个属性     notifyPropertyChanged();  这个方法是当调用的时候,会通知绑定的控件去改变值
 * 作者:卜俊文
 * 创建:2016/8/10 10:20
 * 邮箱:344176791@qq.com
 */
public class Student extends BaseObservable {

    @Bindable
    private String name;

    @Bindable
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(com.example.junwen.databinding.BR.name);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(com.example.junwen.databinding.BR.age);
    }
}

MainActivity主页面



public class MainActivity extends AppCompatActivity {


    private ActivityMainBinding activity_main_binding; //本页面的Binding对象
    private Student student; //学生对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initListener();
    }

    /**
     * 描述:初始化数据
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/10 10:48
     */
    private void initData() {
        //这个就类似于setContentView
        activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        student = new Student("俊文", 22);
        //把Student对象绑定到布局的控件中去,现在开始只要student对象属性变化,控件的值也是相应改变
        activity_main_binding.setStudent(student);
    }

    /**
     * 描述:初始化监听
     * 作者:卜俊文
     * 邮箱:344176791@qq.com
     * 创建时间: 2016/8/10 10:22
     */
    private void initListener() {
        activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                student.setName("卜俊文");
            }
        });
    }

}

五、优劣所在?

优势

(1) DataBinding不需要findviewbyId,只需要根据binding对象去查找到对应的控件。

(2)直接绑定一个对象到XML布局中,当对象的属性变化时,布局中的控件会马上同步变化。

(3)UI代码放到了xml中,布局和数据更紧密

劣势

(1)IDE支持还不那么完善(提示、表达式)

(2)报错信息不那么直接

六、开始编写

(1) 在app / build.gradle 中加入以下字段,即可使用DataBinding框架

dataBinding {   
 enabled = true
}

(2)编写XML,这里给出一个XML模版

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="item"
            type="com.example.junwen.databinding.Student" />
    </data>

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

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

此模块由<Layout>标签作为根节点,里面包含两部分,第一部分是<data>,第二部分就是<LinearLayout>,也就类似于以前我们写布局时的根布局。

其中<data>标签中可以声明对象,变量以及导入包等功能,在这里我导入了Student对象,在下面我需要用到我就可以导入进来,并且起成item的一个别名。

其中<LinearLayout>中,包含了一个TextView,这个TextView的text属性值是这样赋值的(格式必须对):

android:text="@{item.name}"

双引号中 " @{具体变量或者对象的属性值}" ,不只这些,还可以在里面运用表达式,例如上面的例子中的

 android:text="@{String.valueOf(student.age)}"

这个能够在一个属性的后面添加字符串比如下面

android:text="@{item.progress+`%`}"

(3)编写MainActivity

(1)取得Binding对象,这个就类似于setContentView(),返回的对象其实是一个ViewDataBinding,但是我这里写的是ActivityMainBinding,你可以比较一下ActivityMainBinding 和 R.layout.activity_main有什么相似的地方吗?不错,就是拼接起来的,这样就可以获得这个页面的Binding对象。

ActivityMainBinding activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

(2)创建一个Student对象,并且调用setStudent(student)方法,这个方法他会自动生成的,实现了实体与xml绑定。

Student student = new Student("俊文", 22);
//把Student对象绑定到布局的控件中去,现在开始只要student对象属性变化,控件的值也是相应改变
activity_main_binding.setStudent(student)

(3)设置监听,直接通过binding对象查询到按钮控件,这个activityMainStuSetting也会自动生成的,如果遇到没有生成,你需要build一下项目,他就会出来了,执行setName方法,在其内部就会去通知控件更新文本。

activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                student.setName("卜俊文");
            }
        });

七、其他

操作符示例:

(1)判断属性赋值不同的图片

android:src="@{item.checkState.equals(String.valueOf(3)) ? @drawable/ic_task_exit :  @drawable/ic_task_success }" 

(2)设置不同的字符串

android:text='@{error ? "error" : "ok"}'

XML的DataBinding模版XML快速创建

1229.gif

关于DataBinding数据绑定

Android官方数据绑定框架DataBinding

从零开始的Android新项目7 - Data Binding入门篇

Android官方数据绑定框架DataBinding(一)

Android Data Binding代码实战

完全掌握Android Data Binding

数据绑定DataBinding

八、总结

在此就总结了一些基本的DataBind的用法,可能有些地方说的不到位的,也是刚接触不是很熟悉,就是凭自己的理解来说的。

欢迎关注我的微信公众号,分享更多技术文章。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容