Android DataBinding使用总结(二)
来源:互联网 发布:石岐unity3d招聘 编辑:程序博客网 时间:2024/06/05 08:16
前言
在我的上篇文章中,简单学习了DataBinding的环境配置和基本使用:
Android DataBinding使用总结(一)
本文将谷歌官方文档中基本使用方式都进行总结使用,
一、基本的数据绑定
1.可以通过这样的方式创建对象(JavaBean):
/** * Created by QingMei on 2017/5/21 21:31 * email:mei_husky@qq.com * desc:Used to */ public class Student{ public Student(String name, int age) { this.name.set(name); this.age = age; } public int age; public String name ;}
2.在layout文件中,设置:
<?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" xmlns:tools="http://schemas.android.com/tools"> <data> <!--DataBinding支持AutoComplete,所以type填入Student,就可以像在代码里一样进行导包了--> <!--The user variable within data describes a property that may be used within this layout.--> <variable name="student" type="com.mei_husky.samplemvvm.model.Student" /> <variable name="presenter" type="com.mei_husky.samplemvvm.view.activity.DataBindingBaseActivity.Presenter" /> <import alias="Utils" type="com.mei_husky.samplemvvm.util.MyUtils" /> <import type="java.util.List" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.mei_husky.samplemvvm.view.activity.DataBindingBaseActivity"> <!--固定字符 我们可以用 `` 包裹,对应的,外部用""包裹--> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onNameClick(student.name)}" android:text="@{`Student FirstName :` + student.name}" android:textAllCaps="false" android:textSize="14sp" /> <!--使用MyUtils工具类(别名 Utils),在回调方法中返回 age+1 --> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onAgeClick(Utils.addAge(student.age))}" android:text="@{`Student 年龄 :` + student.age}" android:textAllCaps="false" android:textSize="14sp" /> </LinearLayout></layout>
3.然后在activity中:
public class DataBindingBaseActivity extends AppCompatActivity { private ActivityDataBindingBaseBinding binding; private Student student; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); inject(); } private void inject() { binding = DataBindingUtil.setContentView(this, R.layout.activity_data_binding_base); student = new Student("qingMei2", 12); contents.add("content -> 0"); contents.add("content -> 1"); // 以下两种方式 给XML中 student 赋值 // binding.setStudent(student); binding.setVariable(BR.student, student); } public class Presenter { public void onNameClick(String Name) { Toast.makeText(DataBindingBaseActivity.this, Name, Toast.LENGTH_SHORT).show(); } public void onAgeClick(int age) { Toast.makeText(DataBindingBaseActivity.this, String.valueOf(age), Toast.LENGTH_SHORT).show(); } }}
二、Layout Details(布局详解)
1.我们可以在xml的data标签中添加import标签进行导包,这样我们就可以直接调用对应类的方法了
<!--非lang包的类都需要import(比如工具类),然后就可以使用其方法了--><import alias="Utils" //别名 type="com.mei_husky.samplemvvm.util.MyUtils" /><import type="java.util.List" />
2.dataBinding绑定include标签
include标签常用于可复用的layout,我们当然也可以通过dataBinding进行数据绑定,首先创建include标签
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="studentInner" type="com.mei_husky.samplemvvm.model.Student" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:gravity="center" android:text="@{`include 显示StudentName :` + studentInner.name}" android:layout_height="wrap_content" /> </LinearLayout></layout>
然后在xml中使用include标签,将student传给include中的studentInner标签:
<include layout="@layout/include_bind_views" bind:studentInner="@{student}" />
3、xml中我们可以使用的语法:
Common Features
The expression language looks a lot like a Java expression. These are the same:
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:
比如:
android:text="@{String.valueOf(index + 1)}"android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"android:transitionName='@{"image_" + id}'
4.但是这些语法在layout文件中Databinding是不支持的:
this
super
new
Explicit generic invocation(显示泛型调用)
但我们可以通过转义使用泛型:
<!--泛型的支持会在编译时期报红线,但是是可以直接运行的,但是需要通过转义字符才行,如:<数据类型> 或者<数据类型>--> <variable name="contents" type="List<String>" />
5.还有一些补充:
<!--固定字符 我们也可以用 "" 包裹,对应的,外部用``包裹--><TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text='@{"list :"+contents[0]}' /><!--引用资源文件--><TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{`引用资源文件 appName -> ` + @string/app_name}" />
三、数据对象
现在加深一下dataBinding中对Bean的使用,从而实现动态绑定,当数据源改变,UI中对应数据同时改变:
首先是Student的类:
//首先继承 BaseObservale类public class Student extends BaseObservable{ public Student(String name, int age) { this.name.set(name); this.age = age; } /** * ObservableObject 实现数据绑定 * 这里最好是private,否则在xml的代码提示会有两个age(1,成员变量的直接引用 2,代码模板生成),虽然都能用,但强迫症不能忍 */ private int age; @Bindable public int getAge() { return age; } public void setAge(int age) { this.age = age; notifyPropertyChanged(BR.age); } /** * ObservableFields 实现数据绑定(推荐) */ public final ObservableField<String> name = new ObservableField<>();}
1.ObservableObject
一个实现可见接口的类,允许把监听器和对象绑定,以便监听该对象的所有属性的变化。
可见接口有添加和删除侦听器的机制,但数据改变的通知机制取决于开发者。为了使开发更简洁,创建一个基类(BaseObservable)来实现监听器注册机制。当属性改变时,数据实现类仍负责告知机制,其中getter方法加@Bindable注释,并在setter方法中告知属性的变化。
在编译过程中,绑定注释在BR类文件中生成一个条目,然后在模块包中生成BR类文件。如果数据类的基类不可改变,可以使用方便PropertyChangeRegistry有效地存储和通知侦听器的方式来实现可见接口。
除了这种方式,我们还可以通过ObservableFields实现:
2.ObservableFields
创建可见类的过程中,开发人员想节省时间或有很多属性时可以使用可见字段,例如一些常用的可见类型字段:ObservableBoolean, ObservableByte, ObservableChar,ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, andObservableParcelable。
可见字段是有独立字段的可见对象。原始版本在访问操作中避免装箱和拆箱操作。为方便使用,在数据类创建使用public final修饰的字段。
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt();}//通过setter和getter方法获取值user.firstName.set("Google");int age = user.age.get();
3.Observable Collections(可见集合)
一些应用程序使用更多的动态结构来保存数据。可见集合支持键控存取方式访问这些数据对象。当键是一个像字符串这样的引用类型时,可使用ObservableArrayMap。
四、所有代码整合:
1.Student类
//首先继承 BaseObservale类public class Student extends BaseObservable{ public Student(String name, int age) { this.name.set(name); this.age = age; } /** * ObservableObject 实现数据绑定 * 这里最好是private,否则在xml的代码提示会有两个age(1,成员变量的直接引用 2,代码模板生成),虽然都能用,但强迫症不能忍 */ private int age; @Bindable public int getAge() { return age; } public void setAge(int age) { this.age = age; notifyPropertyChanged(BR.age); } /** * ObservableFields 实现数据绑定 */ public final ObservableField<String> name = new ObservableField<>();}
2、在Activity中:
public class DataBindingBaseActivity extends AppCompatActivity { private ActivityDataBindingBaseBinding binding; private Student student; private List<String> contents = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); inject(); } private void inject() { binding = DataBindingUtil.setContentView(this, R.layout.activity_data_binding_base); student = new Student("qingMei2", 12); contents.add("content -> 0"); contents.add("content -> 1"); // 以下两种方式 给XML中 student 赋值 // binding.setStudent(student); binding.setVariable(BR.student, student); binding.setPresenter(new Presenter()); binding.setContents(contents); } public class Presenter { public void onNameClick(String Name) { Toast.makeText(DataBindingBaseActivity.this, Name, Toast.LENGTH_SHORT).show(); } public void onAgeClick(int age) { Toast.makeText(DataBindingBaseActivity.this, String.valueOf(age), Toast.LENGTH_SHORT).show(); } /** * 监听器和对象绑定 ,详情请查看Student类 * {@link Student} */ //ObserableObject 实现动态更新数据 public void onAgeAdd3() { student.setAge(student.getAge() + 3); } //ObservableField 实现动态更新数据(更清晰明了) public void onNameAppendPoint() { student.name.set(student.name.get() + "."); } // Observable Collections public ObservableArrayMap<String, Object> datas = new ObservableArrayMap<>(); { datas.put("string", "我是字符串"); datas.put("int", 1000); datas.put("student", student); } } }
3、layout文件
<?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" xmlns:tools="http://schemas.android.com/tools"> <data> <!--DataBinding支持AutoComplete,所以type填入Student,就可以像在代码里一样进行导包了--> <!--The user variable within data describes a property that may be used within this layout.--> <variable name="student" type="com.mei_husky.samplemvvm.model.Student" /> <variable name="presenter" type="com.mei_husky.samplemvvm.view.activity.DataBindingBaseActivity.Presenter" /> <!--泛型的支持会在编译时期报红线,但可以直接运行,但是需要通过转义字符才行,如:<或者>--> <variable name="contents" type="List<String>" /> <!--非lang包的类都需要import(比如工具类),然后就可以使用其方法了--> <import alias="Utils" type="com.mei_husky.samplemvvm.util.MyUtils" /> <import type="java.util.List" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.mei_husky.samplemvvm.view.activity.DataBindingBaseActivity"> <!--固定字符 我们可以用 `` 包裹,对应的,外部用""包裹--> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onNameClick(student.name)}" android:text="@{`Student FirstName :` + student.name}" android:textAllCaps="false" android:textSize="14sp" /> <!--使用MyUtils工具类(别名 Utils),在回调方法中返回 age+1 --> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onAgeClick(Utils.addAge(student.age))}" android:text="@{`Student 年龄 :` + student.age}" android:textAllCaps="false" android:textSize="14sp" /> <!--通过命名空间 bind include中对应variable的对象--> <include layout="@layout/include_bind_views" bind:studentInner="@{student}" /> <!--固定字符 我们也可以用 "" 包裹,对应的,外部用``包裹--> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text='@{"list :"+contents[0]}' /> <!--引用资源文件--> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{`引用资源文件 appName -> ` + @string/app_name}" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onAgeAdd3()}" android:text="@{`ObservableObjects绑定 age+3`}" android:textAllCaps="false" android:textSize="14sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onNameAppendPoint()}" android:text="@{`ObservableField绑定 name + 「.」`}" android:textAllCaps="false" android:textSize="14sp" /> <!--ObservableMap--> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{`ObservableMap,String =` + presenter.datas[`string`]}" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{`ObservableMap,int =` + presenter.datas[`int`]}" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{`ObservableMap,Student =` + presenter.datas[`student`]}" /> </LinearLayout></layout>
实现效果如图:
五、总结:
本文为DataBinding的学习总结,相对内容较多一些,但都很好理解。
我的其它文章:
Android DataBinding使用总结(三)列表展示
Android MVVM+DataBinding结合Dagger2进行开发
Android 神兵利器Dagger2使用详解(一)基础使用
参考文档:
DataBinding 谷歌官方文档
没有翻墙的用户可以看这篇:
Data Binding Guide——google官方文档翻译
本文中所有代码都已托管在GitHub上面:
Github传送门,点我查看源码
该demo包含本文中所有代码但不仅限于:
使用了 Mvvm+DataBinding 搭建的DemoApp
1.MainActivity
-DataBinding的入门使用以及引导界面
2.DataBindingBaseActivity
-Databinding的所有基本使用方法
3.RecyclerBindActivity
-RecyclerView中使用dataBinding进行列表展示
4.MulTypeRecyclerBindActivity
-RecyclerView中使用dataBinding展示多类型列表
- Android DataBinding使用总结(二)
- android 使用DataBinding问题总结
- Android DataBinding使用总结(一)
- Android DataBinding 项目使用介绍(二)
- Android DataBinding使用详解(二)
- Android DataBinding使用总结(三)列表展示
- Android MVVM之Databinding(二) 使用篇
- Android--DataBinding基础使用
- Android使用DataBinding入门
- android中使用DataBinding
- Android dataBinding 使用记录
- Android Databinding简单使用
- Android DataBinding使用总结(四)多类型列表展示
- Android DataBinding 基础用法二
- Android DataBinding (二) 事件处理
- Android进阶---android databinding 使用
- Android使用DataBinding代替findViewById
- android DataBinding 的简单使用
- chisel入门踩坑
- SQLite加密
- 超级淘背后的秘密,发家致富不是梦
- 【Linux】 JDK安装及配置 (tar.gz版)
- [Python]Numpy安装及一些玄学问题(is not a supported wheel on this platform、Undefined variable from import)
- Android DataBinding使用总结(二)
- python3爬虫无法显示中文问题解决
- 求两字符串最长公共连续子串---C++编程
- 【贪心算法】贪心算法与活动安排问题
- Win10修复Linux引导
- Spring MVC 之 处理Date类型
- 一个安卓锁机病毒的分析报告
- Apache和Tomcat有什么不同,为什么要整合Apache和Tomcat
- POJ 1408 Fishnet 笔记