您的位置:首页 > 移动开发 > Android开发

Android DataBinding使用总结(二)

2017-05-26 19:52 274 查看

前言

在我的上篇文章中,简单学习了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展示多类型列表
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: