Data Binding(数据绑定)---学习笔记

来源:互联网 发布:淘客喵插件mac版 编辑:程序博客网 时间:2024/05/16 10:28

使用前提

  • 添加Data Binding 到gradle构建文件里
android {    ....    dataBinding {        enabled = true        }    }

Data Binding Layout文件

使用 Data Binding 之后,xml的布局文件就不再单纯地展示 UI 元素,还需要定义 UI 元素用到的变量。所以,它的根节点不再是一个ViewGroup,而是变成了 layout(起始根标签),并且新增了一个节点 data

Data Binding表达式

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

在layout的属性表达式写做@{xxx.xxx}

Data对象

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

用于TextView中的android:text属性的表达式@{user.firstName}将访问JavaBeans对象中的getFirstName

Binding数据

默认情况下,一个Binding类会基于layout文件的名称而产生,将其转换为Pascal case(译注:首字母大写的命名规范)并且添加“Binding”后缀。将我们布局文件的首字母大写,并且去掉下划线,将下划线后面的字母大写,加上Binding组成。上述的layout文件是activity_main.xml,因此生成的类名是ActivityMainBinding

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

如果你在ListView或者RecyclerView adapter使用Data Binding时,你可能会使用:

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

自定义Binding名称

<data class=".Custom">...</data>

那么DataBindingUtils.setContentView返回的binding类就是:你的应用包名.Custom

深入Layout文件

  • import
    • 零个或多个import元素可能在data元素中使用。这些只用在你的layout文件中添加引用,就像在Java中:

      <data>
      <import type="android.view.View"/>
      </data>
  • 当类名有冲突时,其中一个类名可以重命名为alias:

    <import type="android.view.View"/>
    <import type="com.example.real.estate.View"
    alias="Vista"/>

    java.lang包里的类,可以不用导包的
 <data>          <import type="org.loader.app2.Student" />          <variable              name="stu"              type="Student" />          <variable              name="str"              type="String"/>          <variable              name="error"              type="boolean"/>          <variable              name="num"              type="int" />      </data>  

Acitivity

    binding.setStu(new Student("loader"));      binding.setStr("string");      binding.setError(false);  

如果给TextView \ ImageView 等布局设置Id后,在Java代码中直接可以这么使用binding.所设置的id

表达式

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text='@{error ? "error" : "ok"}'/>
  • NULL 合并操作运算符
    android:text="@{user.displayName ?? user.lastName}"
    等价于
    android:text="@{user.displayName != null ? user.displayName : user.lastName}"

数据对象

我们可以通过Observable的方式去通知UI数据已经改变,官方为我们提供了更加简便的方式BaseObservable

  • 实体类要继承BaseObservale类
  • 在Getter上使用注解@Bindable
  • 在Setter里调用方法notifyPropertyChanged
public class Student extends BaseObservable {    private String name;    public Student() {    }    public Student(String name) {        this.name = name;    }    @Bindable    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;        //notifyPropertyChanged(org.loader.app4.BR.name);        notifyPropertyChanged(BR.lastName);    }}

BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个 entry。

通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用 notifyPropertyChanged(BR.firstName) 可以通知系统 BR.firstName 这个 entry 的数据已经发生变化,需要更新 UI。

除此之外,还有一种更细粒度的绑定方式,可以具体到成员变量,这种方式无需继承 BaseObservable,一个简单的 POJO(plain-old Java Object) 就可以实现。

public class PlainUser {    public final ObservableField<String> firstName = new ObservableField<>();    public final ObservableField<String> lastName = new ObservableField<>();    public final ObservableInt age = new ObservableInt();}

系统为我们提供了所有的 primitive type 所对应的 Observable类,例如 ObservableIntObservableFloatObservableBoolean 等等,还有一个 ObservableField 对应着 reference type。

BindingAdapter(自定义setter )

<layout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto">    <data class=".Custom">        <variable            name="imageUrl"            type="String" />    </data>    <ImageView        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:image="@{imageUrl}"/></layout>

以bind:开头,接着书写你在控件中使用的自定义属性名称。

public class Utils {    @BindingAdapter({"bind:image"})    public static void imageLoader(ImageView imageView, String url) {        ImageLoaderUtils.getInstance().displayImage(url, imageView);    }}
public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        org.loader.app8.Custom binding = DataBindingUtil.setContentView(this,                R.layout.activity_main);        binding.setImageUrl("http://images.csdn.net/20150810/Blog-Image%E5%89%AF%E6%9C%AC.jpg");    }}

MainActivity中传入的URL到xml文件中的<ImageView app:image"@{imageUrl}"然后进入Utils 绑定BindingAdapter的imageLoader的(…,String url)中

Converters

Converters
====================待更新

学习来源

MasteringAndroidDataBinding
Android官方数据绑定框架DataBinding(一)
Android官方数据绑定框架DataBinding(二)

0 0
原创粉丝点击