本教程介绍数据绑定在Android应用程序中的用法,数据绑定允许将用户界面与应用程序模型和逻辑同步。
1.在Android应用中使用数据绑定
1.1.Android数据绑定介绍
Android提供了使用数据绑定编写声明性布局的支持。这将最小化应用程序逻辑中连接到用户界面元素所需的代码。
使用数据绑定需要更改布局文件。这样的布局文件以layout根标记后跟数据元素和view根元素。数据元素描述可用于绑定的数据看法元素包含根层次结构,类似于未用于数据绑定的布局文件。对布局中数据元素或表达式的引用使用@{}或@={} ,
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="temp" type="com.vogella.android.databinding.TemperatureData"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{temp.location}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{temp.celsius}"/>
</LinearLayout>
</layout>
数据中的用户变量描述了可在此布局中使用的属性。
普通视图层次结构
Android数据绑定生成Binding基于此布局初始化。此类保存来自布局属性的所有绑定,即定义的变量到相应的视图。它还为布局中的数据元素提供生成的setter。生成的类的名称基于布局文件的名称。此名称将转换为Pascal case和Binding添加后缀。例如,如果布局文件被调用activity_main.xml,则调用generate类 活动。您可以通过此类或DataBindingUtil class
TemperatureData temperatureData = // your data is created here
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setTemp(temperatureData); // generated setter based on the data in the layout file
你可以使用inflate方法。这对于在片段中使用数据绑定非常有用,ListView或RecyclerView .
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater(), container, attachToContainer);
// get the root view
View view = binding.getRoot();
// do more stuff
TemperatureData temperatureData = // your data is created here
binding.setTemp(temperatureData); // generated setter based on the data in the layout file
还可以为RecyclerView、ViewPager或其他未设置Activity内容的事物进行布局。
1.2.在Android中启用应用程序绑定
要在Android应用程序中启用数据绑定,请将以下代码片段添加到app/build中。梯度文件。
android {
....
dataBinding {
enabled = true
}
}
1.3.通过侦听器绑定和方法引用进行事件的数据绑定
事件可以直接绑定到处理程序方法,类似于android:onClick可以分配给活动中的方法。事件属性名由侦听器方法的名称控制,但有一些例外。例如, View.OnLongClickListener有一个method onLongClick(),因此此事件的属性为android : onLongClick .
为了将一个事件分配给它的处理程序,使用一个普通的绑定表达式,其值为要调用的方法名。绑定表达式可以为视图分配单击侦听器。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="presenter"
type="com.vogella.android.databinding.MainActivityPresenter"/>
</data>
<Button
android:text="Start second activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{() -> presenter.showList()}"
/>
</layout>
您还可以通过android:onClick="@{handlers::onClickFriend}"/>。如果方法需要参数,也可以将数据对象传递给它们。例如:
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
1.4.进口
也可以导入类以在数据绑定表达式中使用它们。
<data>
<import type="com.example.MyStringUtils"/>
<variable name="user" type="com.example.User"/>
</data>
<TextView
android:text="@{MyStringUtils.capitalize(user.lastName)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
1.5.使用数据模型的更改更新用户界面
任何普通的旧Java对象(POJO)都可以用于数据绑定。但是,如果数据模型中的更新也应更新用户界面,则对象必须能够通知数据更改。有三种不同的数据更改通知机制:observable objects;observable fields;*observable collections
Android提供BaseObservable可以扩展的类。数据类负责在属性更改时通知。这是通过分配@可装订注释getter和setter中的notifying。
package com.vogella.android.databinding;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import java.util.Observable;
public class TemperatureData extends BaseObservable {
private String celsius;
public TemperatureData(String celsius) {
this.celsius = celsius;
}
@Bindable
public String getCelsius() {
return celsius;
}
public void setCelsius(String celsius) {
this.celsius = celsius;
notifyPropertyChanged(BR.celsius);
}
}
定义相关的getter
通知所有侦听器,BR.cellsius是生成的类
每次更新时都会调用此侦听器,并更新相应的视图。这样可以确保模型中的更新也更新UI。
或者,为了创建一个可观察的类,还可以使用ObservableField以及属性的子类
private class TemperatureData {
public final ObservableField<String> celsius = new ObservableField<>();
public final ObservableField<String> location = new ObservableField<>();
}
要访问代码中的此类字段,请使用set和get方法
temp.location.set("Hamburg");
String celsius = temp.celsius.get();
1.6.使用BindingAdapter的自定义转换器
有时您必须执行复杂的数据转换。为此,您可以通过静态@BindingAdapter方法。此方法可以放置在代码中的任何位置,并且可以覆盖字段到数据模型的默认转换。
例如,假设要将数据模型的字段分配给图像视图。
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="@{obj.url}"
/>
您可以在上注册此属性ImageView使用以下方法。此方法使用滑翔下载图像
@BindingAdapter("android:src")
public static void setImageUrl(ImageView view, String url) {
Glide.with(view.getContext()).load(url).into(view);
}
2.练习:在Android应用程序中使用数据绑定
在本练习中,您将学习如何使用数据绑定在用户界面小部件之间进行交互。
2.1.激活数据绑定的使用
打开您的应用程序/内部版本.gradle文件并激活数据绑定的使用。
apply plugin: 'com.android.application'
android {
dataBinding {
enabled = true
}
.... [REST AS BEFORE...]
2.2.为视图交互创建类
创建以下类
package com.vogella.android.databinding;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
public class TemperatureData extends BaseObservable {
private String location;
private String celsius;
public TemperatureData(String location, String celsius) {
this.location = location;
this.celsius = celsius;
}
@Bindable
public String getCelsius() {
return celsius;
}
@Bindable
public String getLocation() {
return location;
}
public void setLocation(String location){
this.location = location;
notifyPropertyChanged(BR.location);
}
public void setCelsius(String celsius) {
this.celsius = celsius;
notifyPropertyChanged(BR.celsius);
}
}
package com.vogella.android.databinding;
public interface MainActivityContract {
public interface Presenter {
void onShowData(TemperatureData temperatureData);
}
public interface View {
void showData(TemperatureData temperatureData);
}
}
package com.vogella.android.databinding;
import android.content.Context;
public class MainActivityPresenter implements MainActivityContract.Presenter {
private MainActivityContract.View view;
private Context ctx;
public MainActivityPresenter(MainActivityContract.View view, Context ctx) {
this.view = view;
this.ctx = ctx;
}
@Override
public void onShowData(TemperatureData temperatureData) {
view.showData(temperatureData);
}
}
2.3.调整布局文件和活动以使用数据绑定
将布局更改为以下内容。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="temp"
type="com.vogella.android.databinding.TemperatureData" />
<variable
name="presenter"
type="com.vogella.android.databinding.MainActivityPresenter"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={temp.location}"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={temp.celsius}"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@={temp.celsius}" />
<Button
android:text="Show data model"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onShowData(temp)}"
android:id="@+id/button" />
</LinearLayout>
</layout>
调整活动代码以使用生成的数据绑定类。
package com.vogella.android.databinding;
import android.app.Activity;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.widget.Toast;
import com.vogella.android.databinding.databinding.ActivityMainBinding;
public class MainActivity extends Activity implements MainActivityContract.View {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainActivityPresenter mainActivityPresenter = new MainActivityPresenter(this, getApplicationContext());
TemperatureData temperatureData = new TemperatureData("Hamburg", "10");
binding.setTemp(temperatureData);
binding.setPresenter(mainActivityPresenter);
}
@Override
public void showData(TemperatureData temperatureData) {
String celsius = temperatureData.getCelsius();
Toast.makeText(this, celsius, Toast.LENGTH_SHORT).show();
}
}
来自:https://www.vogella.com/tutorials/AndroidDatabinding/article.html
网友评论