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

使用前提

  • 添加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

@Override
protected 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);
//or
ListItemBinding 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值