Android中的MVP笔记之三: Data Binding 库的使用之对象数据变化与界面同步更新 4年前

上一节简单的使用Data Binding 库与界面绑定数据与事件处理,当数据更新后,使用mBinding.setCompany(mCompany);方法可以把界面上的数据全部更新一次。

如果只想在类的某个成员变量更新时相应也只更新相对应的界面,而不是layout里绑定的全部数据时,Data Binding 库也提供了相应的类,还提供了一个监听属性字段变化的回调。

 java的基本数据类型都有一个对的包装类。如int对应Integer,long对应于Long,boolean对应Boolean。

类似的Data Binding 库对于成员变量也有相对应的包装类。如下图:

Android中的MVP笔记之三: Data Binding 库的使用之对象数据变化与界面同步更新

1.当类的成员变量值变化时,通知相应的回调接口

1.1新建对应的java类继承BaseObservable,并用Observablexxx包装相应的成员变量,在相应的get方法上使用@Bindable,@BindingAdapter注解,如下所示

public class BRCompany extends BRBaseObservable{ public ObservableField nameField = new ObservableField<>(); public ObservableField iconField = new ObservableField<>(); public ObservableField infoField = new ObservableField<>(); public ObservableLong createTimeField = new ObservableLong();

**public** BRCompany(String name, String icon, String info, **long** createTime) {
    **this**.**nameField**.set(name);
    **this**.**iconField**.set(icon);
    **this**.**infoField**.set(info);
    **this**.**createTimeField**.set(createTime);
}

@BindingAdapter({**"bind:imageUrl"**, **"bind:error"**})
**public static void** setIcon(ImageView view, String url, Drawable error) {
    Glide._with_(view.getContext()).load(url).error(error).into(view);
}

@Bindable

public String getBRName() { return nameField.get(); }

**public void** setName(String name) {
    **this**.**nameField**.set(name);
}

    ...省略n行代码,完整请查看完整工程。 }

做安卓开发的都知道有一个叫EditText的输入控件,在输入内容变化时,有相应的接口回调相应的输入内容(这一个特性其实是EditText的父类TextView的方法,但经常用在EditText输入变化时使用,TextView相对较少使用这一个特性。)

public void addTextChangedListener(TextWatcher watcher) public void removeTextChangedListener(TextWatcher watcher)

public interface TextWatcher extends NoCopySpan { public void beforeTextChanged(CharSequence s, int start,int count, int after); public void onTextChanged(CharSequence s, int start, int before, int count); public void afterTextChanged(Editable s); }

类似的Data Binding 库对成员变量的包装Observablexxx类也有一个类似的方法和回调接口,

public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback)

public abstract static class OnPropertyChangedCallback { public OnPropertyChangedCallback() { }

**public abstract void** onPropertyChanged(Observable var1, **int** var2);

}

使用方法也类似,只是一个是在输入内容发生变化时回调,一个是在调用set方法时回调。

mCompany.nameField.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { Log.d("onPropertyChanged","name:"+mCompany.nameField); } });

2.在成员变量值变化时让layout里绑定这个成员变量的控件也同时变化。

如上面所示,新建相应的java类后,在layout里做相应的引用,注意是以成员变量名称方式引用,即定方义了public ObservableField nameField = new ObservableField<>();是使用brCompany.**nameField ,**而不是使用对应的get方法。

<**LinearLayout ** **android****:layout_width=****"match_parent" ** **android****:layout_height=****"wrap_content"**>

<**TextView

** android:id=****"@+id/tv_name" ** android:layout_width="wrap_content" ** android:layout_height="wrap_content" ** android:layout_weight="1" ** android:text='@{"name:"+brCompany.nameField}' ** android:textSize=****"16sp"** />

<**TextView

** android:id=****"@+id/tv_create_time" ** android:layout_width="wrap_content" ** android:layout_height="wrap_content" ** android:layout_weight="1" ** android:text="@{DateUtil.getTime(brCompany.createTimeField)}" ** android:textSize=****"16sp"** /> </**LinearLayout**>

然后在调用mCompany.setName(s);方法时就可以同步更新界面。

注意事项

Android中的MVP笔记之三: Data Binding 库的使用之对象数据变化与界面同步更新

在生成的临时文件里,会有上面的一个BR文件,和R文件类似,生成的都是一个类似id的属性。

public class Company extends BaseObservable { public String name; private String icon; private String info; private long createTime;     ...省略n行代码。

@Bindable public String getName() { **    return name**;     } }

上面的类生成了图中对应的11~15行数据。

public class BRCompany extends BRBaseObservable{ public ObservableField nameField = new ObservableField<>(); public ObservableField iconField = new ObservableField<>(); public ObservableField infoField = new ObservableField<>(); public ObservableLong createTimeField = new ObservableLong();      ...省略n行代码。 @Bindable public String getBRName() {     return nameField.get();     } }

上面的类生成了图中对应的6~10行数据。

以Company类为例定义了一个public String name;属性,也注解一个方法

@Bindable    public String getName()

所以在layout里可以有两种引用方法

以方法形式引用

android:text=****'@{"name:"+company.getName()}'

以BR文件里生成的name属性形式引用。

android:text=****'@{"name:"+company.name}'

对比使用了上面两个类的成员变量名称,可知其实BR文件里的属性值是根据get方法名称生成的,不是根据属性名称生成的,所有会有一个坑就是,当使用了 Observablexxx包装成员变量n,而且有一个getN的方法里,但在layout使用了BR文件里生成的对应属性形式引用时,Observablexxx包装过的成员变量值发生变化时,界面不会发生变化,所以示例中定义时

public ObservableField nameField = new ObservableField<>();

但对应的get方法不是 getNameField 而是 @Bindable public String getBRName();

所以建议在使用Observablexxxx包装类时,成员变量名字叫name时,不要直接发使作@Bindable注解getName方法,否则可能会造成误解。

还有比较坑的就是,在因为在layout里使用不当造成编译失败的时候,提示不太友好,会很难找出哪里错了。

完整代码请查看

https://git.oschina.net/null_979_4294/MVP-DataBinding1

A
AIKA
取少量学生放入试管,加入过量作业,生成学霸溶液和不溶于水的学渣。过滤,在学渣中加入过量浓试卷,学渣迅速溶解且产生气泡,学霸则无明显现象。
2
发布数
4
关注者
735
累计阅读

热门教程文档

C++
73小节
HTML
32小节
C
14小节
MyBatis
19小节
Gin
17小节
广告