DataBinding学习(三)

1 Observable Binding

前面2节学习了绑定属性和绑定方法,但在使用过程中,我们会发现我的实例对象的属性变了,可UI却没有进行更新,这是万万不能忍的。幸亏安卓官方为我们提供了解决办法。
文档说明如下:

Any plain old Java object (POJO) may be used for data binding, but modifying a POJO will not cause the UI to update. The real power of data binding can be used by giving your data objects the ability to notify when data changes. There are three different data change notification mechanisms, Observable objects, observable fields, and observable collections.

When one of these observable data object is bound to the UI and a property of the data object changes, the UI will be updated automatically.

简单来说,要实现Observable Binding,首先得有一个实现了 android.databinding.Observable的类,为了方便,Android 原生提供了已经封装好的一个类—— BaseObservable,并且实现了监听器的注册机制。


2 Observable Objects

先上文档:

A class implementing the Observable interface will allow the binding to attach a single listener to a bound object to listen for changes of all properties on that object.

The Observable interface has a mechanism to add and remove listeners, but notifying is up to the developer. To make development easier, a base class, BaseObservable, was created to implement the listener registration mechanism. The data class implementer is still responsible for notifying when the properties change. This is done by assigning a Bindable annotation to the getter and notifying in the setter.

大体意思是说,一个类实现了Observable 接口会给它的绑定事件添加一个监听。只要该类的属性进行了变化,就会通过监听来实现UI的更新(观察者模式)。 Observable 接口有方法可以添加和删除监听,但是需要开发者自己去调用。谷歌为了让开发简单就整了一个BaseObservable基类,它的继承子类依然可以实现动态更新UI的效果,它是通过一个 Bindable 的注解方式来实现的。 Bindable注解添加在getter方法上,而调用则是在setter方法中进行(这句话需要手动去实现,别指望自动生成了!!!)。另外,不加注解的话notifyPropertyChanged里面的BR是点不出来属性的。
上代码:

private static class User extends BaseObservable {//官方示例,内部类的写法。可以无视之。
   private String firstName;//可以使用public,关键在于需要调用都后面的get/set方法!!!
   private String lastName;
   @Bindable
   public String getFirstName() {
       return this.firstName;
   }
   @Bindable
   public String getLastName() {
       return this.lastName;
   }
   public void setFirstName(String firstName) {
       this.firstName = firstName;
       notifyPropertyChanged(BR.firstName);
   }
   public void setLastName(String lastName) {
       this.lastName = lastName;
       notifyPropertyChanged(BR.lastName);
   }
}

诶,里面的BR类是什么鬼?

The Bindable annotation generates an entry in the BR class file during compilation. The BR class file will be generated in the module package. If the base class for data classes cannot be changed, the Observable interface may be implemented using the convenient PropertyChangeRegistry to store and notify listeners efficiently.

简单的说,就是BR是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个entry,当我们通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用notifyPropertyChanged(BR.firstName)来通知系统 BR.firstName 这个entry的数据已经发生变化,需要更新 UI。


3 Observable Fields

除2之外,还有一种更细粒度的绑定方式,可以具体到成员变量,这种方式无需继承 BaseObservable,一个简单的 POJO 就可以实现。
以下是官方文档:

A little work is involved in creating Observable classes, so developers who want to save time or have few properties may use ObservableField and its siblings ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable. ObservableFields are self-contained observable objects that have a single field. The primitive versions avoid boxing and unboxing during access operations. To use, create a public final field in the data class:

OK,OK,上面的可以略过,但是最后2句需要注意一下:

The primitive versions avoid boxing and unboxing during access operations. To use, create a public final field in the data class。

翻译过来就是说安卓以前的版本是避免通过操作进行自动拆装箱(JDK1.5新特性http://blog.csdn.net/derson2388/article/details/8026518)。所以现在如果要使用DataBinding就必须在数据类中把属性值设为public final
上菜,哦不,上代码:
数据类:

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

XML文件:

<TextView
     android:layout_width="0dp"
     android:layout_height="60dp"
     android:layout_weight="1"
     android:background="#f00"
     android:text="@{user.firstName}"/>//注意此处取值方式!不是user.firstName.get也不是带括号的那种!

MainActivity类:

user = new User();
user.firstName.set("Google");
binding.setUser(user);
Button btn = (Button) findViewById(R.id.main_btn_change);
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        user.firstName.set("Android");
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, user.firstName.get(), Toast.LENGTH_SHORT).show();
            }
        });
    }
});

这种细粒化的绑定需要注意的就是在XML文件中取值的方式——实例名.属性,后面不用跟get。


4 Observable Collections

2和3绑定的都是一些简单的数据类型,现在来看看较为复杂的集合类型又是如何绑定的呢?
官方文档如是说:

Some applications use more dynamic structures to hold data. Observable collections allow keyed access to these data objects. ObservableArrayMap is useful when the key is a reference type, such as String.

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

In the layout, the map may be accessed through the String keys:

<data>
    <import type="android.databinding.ObservableMap"/>//导包
    <variable name="user" type="ObservableMap&lt;String, Object>"/>//不要问我"&lt;",(一)里有说明。
</data>
…
<TextView
   android:text='@{user["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user["age"])}'//强转int也可
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

ObservableArrayList is useful when the key is an integer:

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

In the layout, the list may be accessed through the indices(索引):

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object>"/>
</data>
…
<TextView
   android:text='@{user[Fields.LAST_NAME]}'//应该为public static final,枚举不推荐在安卓中使用。
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

5 小结

本次主要实现了UI的即时更新,可以通过继承BaseObservable,也可以 构建public final ObservableField实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dinding是一种通过机制,将代码中的数据和XML(UI)进行绑定的技术。它允许双方都能对数据进行操作,并在数据发生变化时自动刷新数据。 在Android中,我们可以使用DataBindingUtil类的方法来创建Databinding实例,即通过DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent)或DataBindingUtil.bindTo(viewRoot, layoutId)方法来得到绑定对象。 Databinding主要解决了Model层与View交互的问题,并且现在也支持双向绑定。它的优势在于可以简化代码,使得数据与UI更紧密地结合。我们可以通过一个登录的例子来进一步感受Databinding的优势。你可以下载并查看一个登录的Demo,或者自己编写相关的例子来深入理解Databinding的用法和好处。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [DataBinding详解](https://blog.csdn.net/peiyuWang_2015/article/details/76945081)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [DataBinding使用教程详解](https://blog.csdn.net/zhangwude2301/article/details/80069972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值