android MVVM开发模式(四)
上节我们讲了自定义的@BindingAdapter,来扩展属性功能的时候,第一步添加了一个自定义属性
这个其实是多余的。(我当时按照自定义view属性去做了,其实data-binding是不用这个的,它的实现原理是找到标记为@BindingAdapter对应属性之后,依据这个函数生成代码即可,这个属性在真正的xml里面,是会去掉的。)
这个是怎么发现的呢?
在继续思考@BindingAdapter的定义时候发现的。因为我们标记的时候,后面的参数可能是任意结构的,而本身属性里面标记的类型是有限的,从这里发现这个问题的。
小插曲 说完了。
我们上一节说了怎么玩@BindingAdapter,我们再来说下它是做什么的
- 通过标记一个静态方法为@BindingAdapter,标记附加值为对应属性。
- 静态方法参数:第一个为view的类型,随后参数就是我们关联的变量类型。
- 目的就是可以自定义任意形式的属性适配器。
我们之前还讲了BaseObservable类 和 @Bindable
- 使用类继承BaseObservable后,然后在属性的前面标记为@Bindable,这个属性则是可以通知的。通过使用 notifyPropertyChanged(BR.age);向界面通知。 参数就是这个属性对应的值。
回顾完成,我们看到了这个现在做的是数据更改,通知给view,没有一个view上面输入数据后,反馈给数据这边。因此我们这节解决这个问题。
我们一起看步骤:
1 setAge函数
- 这里我们多了一个条件判断,判断如果没有变化,停止设置text,原因是如果不设置,因为设置text会引起文本改变回调,回调回来又设置文本,又引起文本改变,继续回调,造成无限循环。
2 再加一个标记适配器
- 参数注意,第二个参数要求是这个InverseBindingListener,原因是我们作为双向通讯,这个作为桥梁。这里我们使用检测文本改变,然后调用 ageAttrChanged.onChange();即可。
3 牵线搭桥
- 关键的标注来了。@InverseBindingAdapter,两个参数,属性 和事件。事件后面的值和上面2里面的标注适配器值一样。
这里我们停一下,思考下,两个适配器
和一个关联
它的逻辑思路是:
适配器ageAttrChanged 来完成TextView的注册文本改变消息处理。里面使用onChange()调用。
关联的来处理onChange()的内部实现,返回值就是你的变量类型。
4 临门一脚
改变@ 为 @= ,变为双向方式
如此一来,达到view的数据变化,传递给数据这边。我们之前讲过如何将数据通知给view。这两个组合起来,则完成了双向通讯。
5 验证
- 这里先设置为28,然后在post里面做文本变更,通知到数据那边,然后数据那边设置一下,反馈给界面验证。
- 这里为什么用post呢?原因是binding内部处理数据是个异步的,所以当前这个消息队列里面,如果我们修改文本,因为文本改变回调还没注册呢,导致数据那边没同步了。(当然实际使用中这个情况很少的啦。)
6代码
https://github.com/luxiaoming/MVVMDemo