上一篇文章介绍了使用 @InverseBindingMethods 实现自定义双向绑定,链接地址databinding之自定义双向绑定(一)。本文将以另外一种方式实现双向绑定。
一、InverseBindingAdapter
- attribute:自定义属性,必填项。比如android:rt
- event:用于触发更改的事件。在数据绑定系统的{@link BindingAdapter}中,它用于在使用双向绑定时设置事件监听器,可选项。如果填写,则使用填写的内容作为event的值;如果不填,在编译时会根据attribute的属性名再加上后缀“AttrChanged”。比如android:rtAttrChanged
二、自定义双向绑定
public class MyInverseBindingAdapter {
@BindingAdapter("android:rt")
public static void setRt(RatingBar rating, float value) {
if (rating == null) return;
if (rating.getRating() == value) return;
rating.setRating(value);
}
@InverseBindingAdapter(attribute = "android:rt", event = "android:ratingAttrChanged")
public static float getRt(RatingBar view) {
if (view == null) return 0f;
return view.getRating();
}
@BindingAdapter(value = {"android:onRatingChanged", "android:ratingAttrChanged"}, requireAll
= false)
public static void setListener(RatingBar view, final RatingBar.OnRatingBarChangeListener listener,
final InverseBindingListener attrChangedListener){
if(attrChangedListener == null){
view.setOnRatingBarChangeListener(listener);
}else{
view.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
if(listener != null){
listener.onRatingChanged(ratingBar,rating,fromUser);
}
attrChangedListener.onChange();
}
});
}
}
}
代码中定义了RatingBar类的android:rt属性,并且定义event属性为android:ratingAttrChanged。同样重新定义了 setRt() 方法,防止死循环的问题。
重点看一下 getRt() 方法:
我们知道当M层发生变化时,会通知V层进行数据更新。也就是说当android:rt属性值发生变化,要获取android:rt的值就需要调用 getRt() 方法。使用 @InverseBindingAdapter 就达到了双向绑定的要求。
三、使用
布局文件
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="rt"
type="Float" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RatingBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numStars="10"
android:rt="@={rt}"
/>
</LinearLayout>
注意使用 @= 表达式。
activity中绑定
final ActivityInverseBindingAdapterBinding binding = DataBindingUtil.setContentView(this,
R.layout.activity_inverse_binding_adapter);
binding.setRt(3f);
Log.e("m---->view",binding.getRt()+"");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.e("view---->m",binding.getRt()+"");
}
},5000);
初始值为3,然后滑动控件,5s后发现控件变化: