官方文档地址:html
https://developer.android.com/intl/zh-cn/tools/data-binding/guide.htmljava
Data Binding Library有什么用?android
每当有新东西出现咱们都喜欢问有什么用?这可不是然并卵的东西,咱们来了解下。服务器
一、是官方支持的MVVM模式框架app
二、能够直接在布局 xml 文件中绑定数据,无需再 findViewById 而后手工设置数据框架
三、能够提升解析XML的速度eclipse
四、UI与功能的解耦合ide
1、环境 布局
在开始使用新东西以前,咱们须要稍微的配置一下环境,这里要求你的Android Studio版本是1.3+,使用eclipse的同窗暂时尚未办法使用该框架,请换用Android Studio。还有,在开始以前,请更新你的Support repository到最新的版本。 学习
万事俱备,那咱们就开始搭配环境!
新建一个project,在dependencies中添加如下依赖
dependencies { classpath "com.android.tools.build:gradle:1.3.0" classpath "com.android.databinding:dataBinder:1.0-rc1" }
因为依赖的项目在 jcenter 服务器中,因此在repositories 中须要添加 jcenter以下:
allprojects { repositories { jcenter() } }
在须要使用支持库的module 的build.gradle文件中添加插件申请:
apply plugin: 'com.android.application' apply plugin: 'com.android.databinding'
例子:如今作一个点击一下按钮而后年龄会+1的小功能,这里也模拟了咱们是数据更新。
第一步:建立XML布局
建立一个布局xml文件,就像之前同样。而后这里咱们须要作一些少少的修改,在这个框架下咱们的思惟要稍稍改变一下了,之前的布局XML只描述了布局,他是相对固定的东西,在Data Binding Library下咱们的布局XML就像是一个类,他能够有变量也能进行必定的运算。其实Data Binding Library还真的给你生成了一个相似这样的类。
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="cn.golditfin.bean.User" /> <variable name="buttonname" type="String" /> </data> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" /> <TextView android:id="@+id/age_textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@{String.valueOf(user.age)}" /> <Button android:id="@+id/age_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:text="@{buttonname}" /> </RelativeLayout> </layout>
其中咱们布局文件的根节点变成了layout,而后定义了变量。
在此布局定义了:
一、两个变量,一个是对象User,一个是String类型的buttonname。
二、两个TextView一个Button
<data> <variable name="user" type="cn.golditfin.bean.User"/> </data>
在 data 元素中使用 variable 来声明在布局文件中使用的变量。
name声明了变量的名称,type声明了变量的类型,变量能够为基本类型如int,也能够为集合或者对象。
View中使用变量用@{} 格式来调用,下面Textview使用了咱们对象user的变量name。
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" />
第二步:定义数据对象
public class User { public String name; public int age; public User(String name,int age){ this.name = name; this.age = age; } }
很简单就两个成员变量
而后是Java代码调用。
第三步:绑定数据
public class MainActivity extends AppCompatActivity { private User myUser; private ActivityMainBinding myBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); myUser = new User("年龄",4); myBinding.setUser(myUser); myBinding.setButtonname("年龄+1"); myBinding.ageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myUser.age++; myBinding.setUser(myUser); } }); } }
在Activity的onCreate方法中进行了基本的数据绑定。一句一句代码给大家解释。
一、原来设置布局的setContentView方法咱们如今不用了,改为了DataBindingUtil.setContentView
二、对于第一点的返回值是框架给咱们生成的类,该类按照单词首字母大写的规则,布局的名字加上Binding组成。好比咱们的布局是activity_main.xml,因此按照这个规则来转换的话就变成了ActivityMainBinding。
三、自动生成的类ActivityMainBinding其实就是表明了那个布局,里面包括了布局的View,咱们声明的变量。咱们能够经过这个对象获取到布局的元素。
四、binding.setUser(user);没错,这里的setUser方法是框架给咱们自动生成的,每个布局中声明的变量都会自动生成对应的get,set方法。
好的,如今咱们跑起来看看。
如今已经实现咱们的想法了,可是看到这里的代码以及咱们实现的过程遇到数据改变不能刷新问题。
当我尝试单方面的进行myUser对象数据更改的时候界面上的数据并不能自动刷新,而后我经过setUser再次设置就能够刷新了,这简直是烦恼啊!
带着这个问题咱们来进一步的学习Data Binding Library。
解决问题
数据刷新自动同步如何完成呢?
解决数据同步其实谷歌已经想到了,在这里提供了两个解决办法。
一、让实体类继承BaseObservable类
public class User extends BaseObservable{ public String name; public int age; public User(String name,int age){ this.name = name; this.age = age; } @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.user); } @Bindable public int getAge() { return age; } public void setAge(int age) { this.age = age; notifyPropertyChanged(BR.user); } }
说明:
一、首先继承BaseObservable类
二、给成员变量的get方法添加@Bindable注解
三、在成员变量的set方法的最后调用方法notifyPropertyChanged,其中里面的参数是在BR类中记录的变量,那些变量就是咱们在XML中声明的那些啦,相似于安卓资源管理的R.java文件,不过这里管理的是布局XML的变量,是自动生成的。
在这里我又有问题要问了,以前个人实体类这么简约,如今变这么长,感受不爽!
那么有没有简约版的呢,由于我很懒不想弄这么多代码?
二、使用Observable数据类型
这是一个简约的方法,谷歌为咱们提供了基于经常使用数据类型的Observable类型,就是咱们熟悉的数据类型前面加上Observable组成。
例如:
Int类型对应ObservableInt
Boolean类型对应ObservableBoolean
其余基本类型相似以上写法。
而String类型对应的是ObservableField<String>,ObservableField是一个泛型
咱们能够看看他的源码
而后再看看ObservableInt的源码
其余类型的源码基本相似。这样看来其实ObservableField除了能够存放对象还能够代替其余全部基本类型来使用。
public class User { public ObservableField<String> name = new ObservableField<>(); public ObservableInt age = new ObservableInt(); public User(String name,int age){ this.name.set(name); this.age.set(age); } }
以上就是进过改造的实体类。
使用Observable数据类型以后数据是经过get,set方法来获取和改变的。
在XML布局中使用时跟原来的数据相似同样。
public class MainActivity extends AppCompatActivity { private User myUser; private ActivityMainBinding myBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); myUser = new User("年龄",4); myBinding.setUser(myUser); myBinding.setButtonname("年龄+1"); myBinding.ageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myUser.age.set(myUser.age.get()+1); } }); } }