DataBinding学习入门篇

来源:互联网 发布:怎么查域名是否备案 编辑:程序博客网 时间:2024/05/17 22:32

1、什么是Data Binding

Data Binding,顾名思义,数据绑定,是Google对MVVM在Android上的一种实现,可以直接绑定数据到xml中,并实现自动刷新。现在最新的版本还支持双向绑定,尽管使用场景不是那么多。Data Binding可以提升开发效率(节省很多以往需要手写的java代码),性能高,功能强。

用途

去掉Activities & Fragments内的大部分UI代码(setOnClickListener, setText, findViewById, etc.)
XML变成UI的唯一真实来源
减少定义view id的主要用途(数据绑定直接发生在xml)
开源方案
ButterKnife, Jake大神的知名库了,可以少些很多findViewById,setOnClickListener,取而代之地用annotation去生成代码。
Android Annotations,同样通过annotation,大量的annotation,侵入性较强,需要遵循其规范写一些代码,像是@AfterViews注释中才能对View进行操作。
RoboBinding,和Data Binding最相似的一个方案,同样很多事情放在xml去做了,使用了aspectJ去做生成。
除了这些比较有名的,还有很多各不相同的方案,但自从data binding发布后,可以说它们都再也没有用武之地了,因为无论从性能、功能,还是ide的支持上,data binding都更好。
优势
UI代码放到了xml中,布局和数据更紧密
性能超过手写代码
保证执行在主线程
劣势
IDE支持还不那么完善(提示、表达式)
报错信息不那么直接
重构支持不好(xml中进行重构,java代码不会自动修改)
使用
1、配置:
配置起来实在很简单,在app模块的build.gradle中加上几行代码就行了。
Gradle:

android {  compileSdkVersion 24  buildToolsVersion "24.0.0"  dataBinding{    enabled = true;  }  ...

2、布局xml编写
与之前我们习惯不同,最外层根节点必须为layout,layout内最多有一个Data节点和一个View节点,View节点必须有且只有一个,data节点可有可无:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools">    <data>        ...    </data>    <RelativeLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            tools:context="com.alvin.databindingdemo.MainActivity">        <TextView                android:text="Hello World!"                android:layout_width="wrap_content"                android:layout_height="wrap_content"/>    </RelativeLayout></layout>

3、通过xml使用DataBindingUtil创建View:
在Activity中可以使用:DataBindingUtil.setContentView(this, R.layout.activity_xxx);
创建View时使用: DataBindingUtil.inflate(inflater,R.layout.activity_xxx,parent,false);
返回值为ViewDataBinding,或子类(子类很方便的设置model,根据id获取view)
这里有个小细节,如果你的xml中未定义 data 或者 id,默认不生成ViewDataBinding的子类,因此xml没写完不要着急编译生成ViewDataBinding的子类。获得binding对象后,你就可以对xml任何元素做任何事情了。
Binding生成规则
默认生成规则:xml通过文件名生成,使用下划线分割大小写。
比如activity_demo.xml,则会生成ActivityDemoBinding,item_search_hotel则会生成ItemSearchHotelBinding。

view的生成规则类似,只是由于是类变量,首字母不是大写,比如有一个TextView的id是first_name,则会生成名为firstName的TextView。

我们也可以自定义生成的class名字,只需要:

<data class=“ContactItem”>…</data>

这样生成的类就会变成ContactItem(一般没必要使用,约定好xml命名即可)。
4、data节点的使用:
data节点可以添加两种元素:
1)variable 定义一个变量,可以是基本数据类型,也可以是抽象数据类型,该变量可以通过binding去set进来,然后被View节点访问。该元素需要声明两个属性,name和type,基本数据类型就是Java中的八种,抽象数据类型需要在type中写上全类名,这个比较好理解。而View对变量的访问只需要在@{}表达式中加入。另外变量也可以用来作为观察者模式的观察者,去绑定事件。
如:

    <data>        <variable name="text" type="String"/>        <variable name="user> type="com.alvin.entity.User"        ...        <TextView                android:text="@{text}"                android:layout_width="wrap_content"                android:layout_height="wrap_content"/>        <TextView                android:text="@{user.username}"                android:layout_width="wrap_content"                android:layout_height="wrap_content"/>        ...    </data>

在Java代码中,需要通过binding对象传入变量值:

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);binding.setText("alvin");binding.setUser(user);//or://binding.setVariable(BR.text,text);//binding.setVariable(BR.user,user);//ViewDataBinding中的方法,不常用,可以尝试一下
注意该语法,@{} 只要是用到databinding,必须要使用该表达式,否则databinding不生效,这是在使用中容易因为粗心犯的错误,笔者吃过一次亏。而我们开发中经常会遇到这种需求,就是除了model中数据要显示,数据前后还要添加固定文字,比如要显示:“姓名:Alvin”,前面的“姓名:”是固定文字,这个怎么处理呢?,最佳实践就是使用strings资源的格式化。用法如下,先在strings文件中定义:<string name="name_format">姓名:%s</string>然后在布局文件TextView中引用:android:text="@{@string/name_format(user.username)}"即可.至于格式化的数据类型可参考文章: [JAVA字符串格式化-String.format()的使用](http://blog.csdn.net/lonely_fireworks/article/details/7962171)

同时呢,你也可以定义一个EventListener的接口或者类,

public interface EventListener{    void onTextClick(Context context,String text);}

xml中定义eventListener变量,并绑定事件

    <variable         name="eventListener"         type="com.alvin.databindingdemo.MainActivity.EventListener"/>    ...    <TextView                android:text="@{@string/name_format(text)}"                android:layout_width="wrap_content"                android:onClick="@{()->eventListener.onTextClick(context,text)}"                android:layout_height="wrap_content"/>    ...

Java代码中设置:

binding.setEventListener(new EventListener() {            @Override            public void onTextClick(Context context,String text) {                Toast.makeText(context,text + " 被点击了",Toast.LENGTH_SHORT).show();            }        });

这里写图片描述
这里要注意两点,首先你定义的EventListener是public的,能够被databinding访问到的,另外更重要一点,事件绑定有两种方法实现,一种是常规使用setOnClickListener的方式实现,另外一种是通过Lambda表达式实现。
第一种很容易理解,和在Activity中定义public的onXXXClick(View v) 方法,然后用onClick属性去指定是一样的,只不过使用Databinding后可以将该方法灵活的定义在别的地方。
第二种我更加推荐,因为我们可以很自由的自定义回调方法的参数列表,向回调方法里传入xml中定义的变量,甚至是context,而学过Lambda表达式的童鞋很容易看懂“()->eventListener.onTextClick(context,text)”的含义,即new一个只有一个方法的接口或类,()表明该接口或类的声明的方法不需要传参(需要传参只需要写入变量名即可,不需要声明类型,如我们需要得到被点击的View,只需要写一个v即可,于是方法在调用时就可以传入v,供事件处理者去访问),->指向方法的具体实现,此处为一行代码,即调用eventListener的onTextClick方法,传入context,text
假设我们需要用到被点击的View,只需要将代码做以下更改即可:

public interface EventListener{    void onTextClick(View v,Context context, String text);}...@Overridepublic void onTextClick(View v, Context context, String text) {        Toast.makeText(context,v.toString() + " 被点击了",Toast.LENGTH_SHORT).show();    }});...android:onClick="@{(v)->eventListener.onTextClick(v,context,text)}"

很easy吧,我反正是这么感觉的。(^__^) 嘻嘻……
2)import引用一个类型,和java的导包很类似,有以下几种用途:引入一个类型后,再声明该类型变量时,type属性只需要写类型而不需要写全类名(Java代码中也是如此),可以直接使用该类型访问类中的静态公开的静态成员变量或方法。
直接贴代码:

<import type="com.alvin.databindingdemo.MainActivity.EventListener"/><variable name="eventListener" type="EventListener"/><import type="android.view.View"/><variable name="show" type="boolean"/>...<TextView        android:text="hello"        android:visibility="@{show?View.VISIBLE:View.GONE}"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/>

细心的童鞋发现了@{}表达式中还可以放三目运算符,对的,这样可以很方便的通过一个boolean变量去控制一个View的显示和隐藏。这仅仅是对类的静态成员的访问,静态方法也可以调用,比如String.valueof(Object o),读者也可以自己定义一个工具类,提供静态方法,然后在@{}表达式中调用,这里笔者不在赘述。
今天先写到这儿,未完待续。

0 0
原创粉丝点击