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

Stella981
• 阅读 404

上一节简单的使用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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
皕杰报表(关于日期时间时分秒显示不出来)
在使用皕杰报表设计器时,数据据里面是日期型,但当你web预览时候,发现有日期时间类型的数据时分秒显示不出来,只有年月日能显示出来,时分秒显示为0:00:00。1.可以使用tochar解决,数据集用selecttochar(flowdate,"yyyyMMddHH:mm:ss")fromtablename2.也可以把数据库日期类型date改成timestamp
Stella981 Stella981
2年前
Kerberos无约束委派的攻击和防御
 0x00前言简介当ActiveDirectory首次与Windows2000Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身份验证并需要授权用户更新后端数据库服务器上的记录的方案。这通常被称为Kerberosdoublehopissue(双跃点问题),
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Stella981 Stella981
2年前
ReactNative state更新,视图不更新的问题
开发中遇到这样的问题,我更新了state一个数组的某个元素的选中状态,打印出的数据也显示修改正确了,但是界面却没更新。例如下图点击某项修改选中状态。!(https://oscimg.oschina.net/oscnet/c3291a62b5f638d1e35dd7a719ade39f226.png)代码中之前是这样写的,结果界面没有更新。
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这