双向绑定的实现原理与样板代码

双向绑定的方法有几种这里用到的是借助@BindingAdapter来实现。无项
就是xml里面有一个model,你设置进去了,它就更新就是了。纯单项 ,所谓单项 ,就是你调用一个值set就可以让view变化,这需要@Bindable@ notifyPropertyChanged(BR.title);双项是值 可以修改值来改变view的状态 或者通过修改view的状态来实现修改model的值 这就是你中有我我中有你.

model继承extends BaseObservable
然后set里面设置
这需要@BindingAdapter @InverseBindingAdapter
@BindingAdapter是方便xml里面设置用的。 比如里面定义 @BindingAdapter("intvalue")就可以使用xxx:@{xxx.xx}

class BBB extends BaseObservable{

    @Bindable//有了注解这个才会生成BR.title
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
        notifyPropertyChanged(BR.title);//双向绑定通知改变,不通知就不会生效。
    }
}

单项绑定的我不想再说了,直接上高阶代码

下面代码实现 int类型编辑框的双向生效,修改编辑框内容的时候model值变化,修改model值得时候编辑框内容变化。

任意创建一个类定义下面几个静态方法

第一个方法代表 修改view,

@BindingAdapter("intvalue")
    public static void setTextIntValue(TextView view, int value) {

第二个方法代表修改model

@InverseBindingAdapter(attribute = "intvalue", event = "intvalueAttrChanged")
    public static int getTextIntValue(TextView view) {

第三个方法代表修改model的触发条件在里面设置view监听然后调用onChange从而触发调用第二个方法。

@InverseBindingAdapter(attribute = "intvalue", event = "intvalueAttrChanged")

第二个方法的event对应的是第三个方法的@BindingAdapter("intvalueAttrChanged")

用法:
在xml里面定义

<EditText

app:intvalue="@={model.age}"
/>

触发原理:
编译后会生成一个databindimpl,它会根据注解生成viewbinding生成一个类,
里面的代码就是把第三个方法的代码拷贝一份进行设置监听,
当你修改编辑框内容的时候监听触发了,onChange,onChange()这是代表view改变,我之前说过是会通知model改变,model的改变为第二个方法,getxxint ,你可以尝试写死一个值,你会发现这个值在model里面生效了。

当你通过set器修改model的值,通过model里面定义的

notifyPropertyChanged(BR.title);/

就会触发view的修改,但是这里是个死循环,
这双向绑定不需要加notifyPropertyChanged(BR.title);或者加一个判断,
当然我这里之所以还是加上了,是我监听的不对,我写在了onTextChanged里面。
直接不加上notifyPropertyChanged也能修改,但是光标位置不对,感觉不太爽,所以解决方法就是调整一下回调通知或者不加判断。

/**
     * 根据model的值来设置 view的值 双向绑定 ,setValue Model 不需要加notifyFieldChanage() 否则死循环 除非文本判断。
     **/
    @BindingAdapter("intvalue")
    public static void setTextIntValue(TextView view, int value) {
//        final TextWatcher oldValue = ListenerUtil.trackListener(view, null, R.id.textWatcher);

        if(ParseUtil.parseInt(view.getText().toString()) ==value){//0 or "" ==0 找到死循环的原因了,现在不需要加这句话了。
            return;
        }

        if(value==0){
            view.setText("");//可以在失去焦点的时候设置。
        }else{
        view.setText(value + "");
        }
//        if(oldValue!=null){
//        view.addTextChangedListener(oldValue);
    }


    /**
     * 在onChange 里面调用本方法获得返回值, 然后来修改模型的值.
     *
     * @param view
     * @return
     */
    @InverseBindingAdapter(attribute = "intvalue", event = "intvalueAttrChanged")
    public static int getTextIntValue(TextView view) {
        return ParseUtil.parseInt(view.getText().toString());
    }




@BindingAdapter("intvalueAttrChanged")
    public static void intValueChangeBind(final TextView view,
                                          final InverseBindingListener changeBindListener) {
        TextWatcher watcher =null;
        if(changeBindListener!=null){
                watcher = new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {


                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                        changeBindListener.onChange();


                }

                @Override
                public void afterTextChanged(Editable s) {
                }
            };

        }else{
        }
//            view.addTextChangedListener(watcher);//下面的话没有任何意义 //下面的话加不加都解决不了死循环的问题 只能用判断来解决死循环 addTextChangedListener可能是这句话导致
         final TextWatcher oldValue = ListenerUtil.trackListener(view, watcher, R.id.textWatcher);
            if (oldValue != null) {
                view.removeTextChangedListener(oldValue);
            }
            if (watcher != null) {
                view.addTextChangedListener(watcher);
            }
    }

更多databind请访问我的其它文章。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值