1. 程式人生 > >Android DataBinding 雙向繫結

Android DataBinding 雙向繫結

之前 databinding 框架並不支援 雙向繫結,最新的版本支援了,但是用起來還算方便
以前使用的時候 是這樣繫結的

 <CheckBox
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:checked="@{checked}"
   />

現在只需要在對應的屬性 @{} 改為 @={}

想看下 具體他是那裡配置這個東西的,發現 這些都是在這個包裡面

android.databinding.adapters

然而 用checkbox 來說,這個包裡面並沒有checkbox 專用的 adapter,但是發現了這個CompoundButtonBindingAdapter,ok 應該就是這裡了

然後跟蹤到裡面發現多了兩個註解

@InverseBindingMethods({
        @InverseBindingMethod(type = CompoundButton.class, attribute = "android:checked"),
})

還有方法

 @BindingAdapter(value = {"android:onCheckedChanged", "android:checkedAttrChanged"},requireAll = false)
    public static void setListeners(CompoundButton view, final
OnCheckedChangeListener listener, final InverseBindingListener attrChange) { if (attrChange == null) { view.setOnCheckedChangeListener(listener); } else { view.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public
void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (listener != null) { listener.onCheckedChanged(buttonView, isChecked); } attrChange.onChange(); } }); } }

發現 多了個 android:checkedAttrChanged,這個事件繫結 這個應該是根據上面的那個 InverseBindingMethod attribute =”android:checked” 來命名的,然後方法引數也多了個 listenerfinal InverseBindingListener attrChange, 這個會在 你使用@=的時候 會注入進來。

具體的還沒試試自己寫的view 的其他屬性雙向繫結,應該自定義view 要雙向繫結屬性也需要自己寫這樣的adapter

下面是仿照 寫的一個edittext 雙向繫結
View

package com.ygsoft.testbinding;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;

/**
 * Created by chenzipeng on 2016/6/22.
 */
public class AView extends EditText {

    private String name;

    public AView(Context context) {
        super(context);
    }

    public AView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Adapter

package com.ygsoft.testbinding;

import android.databinding.BindingAdapter;
import android.databinding.BindingMethod;
import android.databinding.BindingMethods;
import android.databinding.InverseBindingListener;
import android.databinding.InverseBindingMethod;
import android.databinding.InverseBindingMethods;
import android.databinding.adapters.ListenerUtil;
import android.text.Editable;
import android.text.TextWatcher;

/**
 * Created by chenzipeng on 2016/6/22.
 */

@BindingMethods({
        @BindingMethod(type = AView.class, attribute = "name", method = "setName")//定義繫結的方法
})

@InverseBindingMethods({
        @InverseBindingMethod(type = AView.class, attribute = "name")//這裡有個event屬性,如果不填預設event為 attribute+"AttrChanged" ,比如這裡就是nameAttrChanged
})
public class AViewBindingAdapter {

    @BindingAdapter(value = {"nameAttrChanged"}, requireAll = false)//這裡的evnet 與 @InverseBindingMethod 的event屬性相同,requireAll這裡意義不明,有可能在多個引數的時候要求所有都要注入
    public static void setName(AView aView, final InverseBindingListener nameAttrChange) {

        TextWatcher newWatcher = 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) {
                nameAttrChange.onChange();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        };

        TextWatcher oldWatcher = ListenerUtil.trackListener(aView, newWatcher, R.id.textWatcher);

        if (nameAttrChange != null) {
            aView.addTextChangedListener(newWatcher);
        }

        if (oldWatcher != null) {
            aView.removeTextChangedListener(oldWatcher);
        }
    }

}