Android Databinding 的简单使用(上)

911 阅读5分钟
原文链接: www.jianshu.com

首先,做个自我反省。
仔细的总结了下这大半年的时间,发现自己并没有在进度,反而是一直吃着老本,归根揭底是自我懒惰。


Paste_Image.png

好了,进入正题

Data Binding Library

官方原文地址: 需要科学上网查阅
developer.android.com/topic/libra…

这篇文章旨在使用Data binding 进行声明式布局构建,尽可能的减少冗余代码。

  • data binding 支持v7 版本以及更高的版本。
  • 如果想要使用data binding, 确保你的android studio的gradle 插件版本在1.5.0-alpha1之上。如果你还是Eclipse的用户,不建议你继续阅读。

Build Environment

在你的项目模块的build.gradle配置

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

当然,还需要确保你的android studio版本在1.3之上,在我写下这篇文章的时候,android studio 的release版本是2.2.+,建议尽可能使用2.+版本。

Data Binding Layout Files

* 1、Writing your first set of data binding expressions

data binding的布局,是在传统的布局文件之上加以改造而成,将跟结构变成了layout,在layout结构目录中,填充了data和传统的view,view的使用没有任何区别。大体如下结构:

<?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>

我们看上面的xml部分,只要注意<data>节点, 这里的代码

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

这里是对实体类与xml的绑定。

绑定完成之后,使用${}表达式进行数据的展示。(😄,如果之前写过j2ee,对于这种页面中绑定应该会秒懂。)

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

* 2、Data Object

假设存在如下的数据实体映射类User

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

这种写法的实体类,创建之后类的字段值就不会改变了,一般适用于只访问一次的情况。另外,也会有另一种实体类写法。

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;
   }
}

从data binding的使用角度来说,这两种方式使用上是一样的。使用 @{user.firstName} 进行数据的获取展示。在第一种写法中,映射的是firstName字段;而在第二种写法中,会去映射getLastName()方法。另外,如果firstName()方法存在的话,也是可以映射到。

* 3、Binding Data

在默认情况下data binging会生成一个和layout文件同名的类文件,这个类文件以Binding结尾。
假设上面的layout文件名称为main_activity.xml,那么会生成一个 MainActivityBinding,这个类将持有绑定的layout文件属性,并且为layout属性分配值。

@Override
protected 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);
}

ok,你现在可以运行代码,查看并测试你的ui了。另外,也可以使用view进行绑定操作。

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

如果你是在ListView或者RecycleView的Adapter中使用,我想你更喜欢这种方式。

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

* 4、Event Handling

data binding允许你通过表达式与onClick进行绑定处理事件分发。我们有两种方法可以进行事件处理

  • Method References : 在表达式中,可以引用符合listener方法签名的方法。当表达式计算为方法引用时,数据绑定会将方法引用和所有者对象封装在一起,并设置监听。如果表达式计算为NULL,则不会进行监听绑定,会设置一个空的监听。
  • Listener Bindings: 使用lambda表达式的方式,数据绑定总是会创建监听器,并设置绑定视图。在事件派发的时候,在进行评估。

* Method References

类似于android:onClick的方式绑定在Activity中,相比较于View#onClick来说的话的优势是method references方法是在编译的时候就能做出检查来,如果映射方法不存在,就会编译的时候抛出错误❌。

method references和传统listener binding的主要区别是: 在数据绑定时,实际的listener将会创建,和listener时在事件触发时。因此如果你希望在事件触发时对表达式进行评估,则应该使用listener binding。

public class MyHandlers {
    public void onClickFriend(View view) { ... }
}

绑定表达式可以派发事件到view中

<?xml version="1.0" encoding="utf-8"?>
<layout     xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.Handlers"/>
       <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}"
           android:onClick="@{handlers::onClickFriend}"/>
   </LinearLayout>
</layout>

注意表达式中的方法签名必须与listener中的方法签名完全匹配。

* Listener Bindings

Listener Bindings 在方法触发时绑定表达式。该功能在Android Gradle Plugin For Cradle Version 2.0 + 可使用。

在method references中,方法参数必须与事件监听匹配。而在listener bindings中,只要你的返回值与监听返回值匹配即可。

public class Presenter {
    public void onSaveClick(Task task){}
}

<?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>

如果你需要使用view参数的话,你也可以写成这样。

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

或者你需要传递两个参数的情况:

public class Presenter {
    public void onSaveClick(View view, Task task){}
}

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

三元运算也是可以的:

 android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"

这部分翻译就到这里了。个人英语能力有限,如果有错误欢迎指正。thx!!!