数据绑定库|Android开发者 (一) [U01]

来源:互联网 发布:复合视频矩阵 编辑:程序博客网 时间:2024/05/20 03:37

来源:https://developer.android.google.cn/topic/libraries/data-binding/index.html(英文)(可直接访问)

翻译方式:chrome自带翻译


本文档介绍了如何使用数据绑定库来编写声明性布局,并最大限度地减少绑定应用程序逻辑和布局所需的粘贴代码。

数据绑定库提供了灵活性和广泛的兼容性 - 它是一个支持库,因此您可以将其与所有Android平台版本一起使用回到Android 2.1(API级别为7+)。

要使用数据绑定,需要Android Plugin for Gradle 1.5.0-alpha1 或更高版本。了解如何更新Gradle的Android插件。

这里写图片描述


建立环境

要开始使用数据绑定,请从Android SDK管理器的支持信息库中下载库。

要将应用程序配置为使用数据绑定,请将dataBinding 元素添加到build.gradle应用程序模块中的文件中。

使用以下代码片段来配置数据绑定:

android {    // ....    dataBinding {        enabled = true    }}

这里写图片描述

如果您有一个依赖于使用数据绑定的库的应用程序模块,则应用程序模块也必须在其build.gradle 文件中配置数据绑定。

另外,请确保您使用的兼容版本的Android Studio。 Android Studio 1.3及更高版本支持数据绑定,如Android Studio支持数据绑定中所述。


数据绑定 布局文件

编写第一组数据绑定表达式

数据绑定布局文件略有不同,从布局的根标记开始, 后跟数据元素和 视图根元素。此视图元素是您的根在不绑定布局文件中的位置。示例文件如下所示:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">   <data>       <variable name="user" type="com.example.User"/>   </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="@{user.firstName}"/>       <TextView android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:text="@{user.lastName}"/>   </LinearLayout></layout>

用户变量中的数据描述了可以此布局中使用的性质。

<variable name="user" type="com.example.User"/>

布局中的表达式使用“ @{}”语法写入属性属性。这里,TextView的文本设置为userName的firstName属性:

<TextView android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:text="@{user.firstName}"/>

数据对象

我们现在假设你有一个简单的Java对象(PO​​JO)for User:

public class User {   public final String firstName;   public final String lastName;   public User(String firstName, String lastName) {       this.firstName = firstName;       this.lastName = lastName;   }}

这种类型的对象具有从不改变的数据。在应用程序中通常会读取一次数据,从此不会更改。也可以使用JavaBeans对象:

public class User {   private final String firstName;   private final String lastName;   public User(String firstName, String lastName) {       this.firstName = firstName;       this.lastName = lastName;   }   public String getFirstName() {       return this.firstName;   }   public String getLastName() {       return this.lastName;   }}

从数据绑定的角度来看,这两个类是等价的。@{user.firstName}用于TextView android:text属性的表达式将访问firstName前一类中的字段和getFirstName()后一类中的方法。或者,firstName()如果该方法存在也将被解决。


Tip
项目build,才会自动生成数据绑定类。


绑定数据

默认情况下,将根据布局文件的名称生成一个Binding类,将其转换为Pascal大小写,后缀为“Binding”。
上面的布局文件就是main_activity.xml生成类 MainActivityBinding。
此类将布局属性(例如user变量)的所有绑定保存到布局的“视图”中,并知道如何为绑定表达式分配值。创建绑定的最简单方法是在 inflating 时执行此操作:

@Overrideprotected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);   User user = new User("Test", "User");   binding.setUser(user);}

你完成了!运行应用程序,您将在UI中看到Test User。
这里写图片描述
或者,您可以通过以下方式获取视图:

MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());

如果您在ListView或RecyclerView适配器中使用数据绑定项,则可能更喜欢使用:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);//orListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

事件处理

数据绑定允许您编写表达式处理从视图分派的事件(例如onClick)。事件属性名称由侦听器方法的名称控制,但有一些例外。例如,View.OnLongClickListener有一个方法onLongClick(),所以这个事件的属性是android:onLongClick。处理事件有两种方法。

  • 方法引用:在您的表达式中,可以引用符合侦听器方法签名的方法。当表达式计算为方法引用时,数据绑定将方法引用和所有者对象包装在侦听器中,并在目标视图上设置侦听器。如果表达式求值为空,则数据绑定不会创建侦听器,而是设置null侦听器。

  • 侦听器绑定:这些是在事件发生时进行评估的lambda表达式。数据绑定总是创建一个监听器,它在视图中设置。调度事件时,侦听器将评估lambda表达式。


方法参考

事件可以直接绑定到处理程序方法,类似于 android:onClick可以分配给Activity中的方法的方式。与View#onClick属性相比的一个主要优点是在编译时处理表达式,因此如果方法不存在或其签名不正确,则会收到编译时错误。

方法引用和侦听器绑定之间的主要区别在于当数据绑定时创建实际的侦听器实现,而不是触发事件时。如果您希望在事件发生时评估表达式,则应使用监听器绑定。

要将事件分配给其处理程序,请使用正常的绑定表达式,其值为要调用的方法名称。例如,如果您的数据对象有两种方法:

public class MyHandlers {    public void onClickFriend(View view){        Log.d(TAG, "onClickFriend: click1 ...");    }}

绑定表达式可以为视图分配点击监听器:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">    <data>        <variable            name="handler"            type="com.zet.learndatabinding.event.MyHandlers"/>        <variable            name="user"            type="com.zet.learndatabinding.bean.User"/>    </data>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@{user.firstName}"/>        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@{user.lastName}"/>        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="@{handler::onClickFriend}"            android:text="click1"            android:textAllCaps="false"/>    </LinearLayout></layout>

请注意,表达式中方法的签名必须与侦听器对象中的方法的签名完全匹配。

// MainActivity.java// set变量@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);        User user1 = new User("Test", "User");        MyHandlers myHandlers = new MyHandlers();        binding.setUser(user1);        binding.setHandler(myHandlers);    }

侦听器绑定

侦听器绑定是在事件发生时运行的绑定表达式。它们类似于方法引用,但它们允许您运行任意数据绑定表达式。此功能适用于Gradle版本2.0及更高版本的Android Gradle Plugin。

在方法引用中,方法的参数必须与事件侦听器的参数相匹配。在侦听器绑定中,只有你的返回值必须与侦听器的预期返回值相匹配(除非它是期望的void)。例如,您可以有一个演示者类具有以下方法:

/** * 任务类 */public class Task {    // ...}
public class Presenter {    public void onSaveClick(Task task) {        Log.d(TAG, "onSaveClick: click2 execute ...");    }}

然后,您可以按照以下方式将click事件绑定到您的布局:

  <?xml version="1.0" encoding="utf-8"?>  <layout xmlns:android="http://schemas.android.com/apk/res/android">      <data>          <variable name="task" type="com.android.example.Task" />          <variable name="presenter" type="com.android.example.Presenter" />      </data>      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"          android:onClick="@{() -> presenter.onSaveClick(task)}" />      </LinearLayout>  </layout>
// MainActivity.java 代码// 设置变量 @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);        User user1 = new User("Test", "User");        binding.setUser(user1);        MyHandlers myHandlers = new MyHandlers();        binding.setHandler(myHandlers);        Task task = new Task();        binding.setTask(task);        Presenter presenter = new Presenter();        binding.setPresenter(presenter);    }

侦听器由只能作为表达式的根元素允许的lambda表达式表示。

Java 8的Lambda及其在Android 开发中的应用
https://segmentfault.com/a/1190000002806957

当表达式中使用回调时,数据绑定会自动为事件创建必要的侦听器和注册。当视图触发事件时,数据绑定会计算给定的表达式。与常规绑定表达式一样,您仍然可以获取数据绑定的null和线程安全性,同时正在评估这些侦听器表达式。

请注意,在上面的示例中,我们尚未定义view传入的参数onClick(android.view.View)。侦听器绑定为侦听器参数提供了两个选择:您可以忽略该方法的所有参数或全部名称。如果您喜欢命名参数,可以在表达式中使用它们。例如,上面的表达可以写成:

android:onClick="@{(view) -> presenter.onSaveClick(task)}"

或者如果要在表达式中使用参数,则可以按如下方式工作:

public class Presenter {    public void onSaveClick(View view, Task task) {        Log.d(TAG, "onSaveClick: click3 execute ...");    }}
android:onClick="@{(view) -> presenter.onSaveClick(view, task)}"

您可以使用具有多个参数的lambda表达式:

public class Presenter {    public void onCompletedChanged(View view, Task task, boolean completed) {        Log.d(TAG, "onCompletedChanged: click4 execute ..." + completed);    }}
<CheckBox            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="@{(view) -> presenter.onCompletedChanged(view, task, isChecked)}"            />

onClick() ==》 多参数方法, 头一个参数必须为View, 否则data binding error

如果您正在侦听的事件返回一个不是类型的值,则void表达式也必须返回相同类型的值。例如,如果要监听长时间点击事件,您的表达式应该返回boolean。

public class Presenter {    public boolean onLongClick(View view, Task task){        Log.d(TAG, "onLongClick: click5 ...");        return false;    }}
android:onLongClick="@{(view) -> presenter.onLongClick(view, task)}"

代码运行,没事,就是as提示属性不存在。。。

如果由于null对象而无法评估表达式,则Data Binding将返回该类型的默认Java值。例如,null对于参考类型,0for int, falsefor boolean等

如果您需要使用具有谓词(例如三元)的表达式,则可以使用 void一个符号。

public void doSomething(View view){        Log.d(TAG, "doSomething: click6 ...");    }
android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"

错误信息显示isVisible()方法不存在,只好改成下面的了

android:onClick="@{(view) -> view.getVisibility() != view.GONE ? presenter.doSomething(view) : void}"

避免复杂的侦听器

监听器表达式非常强大,可以使您的代码非常容易阅读。另一方面,包含复杂表达式的监听器使您的布局难以阅读和不可维护。这些表达式应该像将UI中的可用数据传递给您的回调方法一样简单。您应该在从监听器表达式调用的回调方法中实现任何业务逻辑。
存在一些专门的点击事件处理程序,它们需要除了android:onClick避免冲突以外的其他属性 。已创建以下属性以避免此类冲突:

类 听众设定者 属性
SearchView setOnSearchClickListener(View.OnClickListener) android:onSearchClick
ZoomControls setOnZoomInClickListener(View.OnClickListener) android:onZoomIn
ZoomControls setOnZoomOutClickListener(View.OnClickListener) android:onZoomOut


github个人示例代码
https://github.com/dzetAndroid/LearnDataBinding


end

原创粉丝点击