使用@InverseBindingAdapter / AttrChanged的Android Spinner双向绑定不起作用

时间:2016-10-17 09:18:26

标签: android android-databinding

我已经尝试了一段时间在Spinner上设置双向绑定。

网上有很多这样的例子,这里有堆栈溢出,但它们都不适用于我。

它只是一个国家的微调器,我已经用这种方法为它定义了一个国家适配器:

@InverseBindingAdapter(attribute = "selectedCountry", event = "selectedCountryAttrChanged")
public static String bindCountryInverseAdapter(AppCompatSpinner pAppCompatSpinner) {
    Object selectedItem = pAppCompatSpinner.getSelectedItem();
    SpinnerAdapter adapter = pAppCompatSpinner.getAdapter();
    if (adapter instanceof CountrySpinnerAdapter) {
        return (String) selectedItem;
    }
    throw new UnsupportedOperationException("The adapter must be a CountrySpinnerAdapter");
}

@BindingAdapter(value = "selectedCountryAttrChanged", requireAll = false)
public static void bindCountryChanged(AppCompatSpinner pAppCompatSpinner, final InverseBindingListener newTextAttrChanged) {
    AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            newTextAttrChanged.onChange();
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            newTextAttrChanged.onChange();
        }
    };
    pAppCompatSpinner.setOnItemSelectedListener(listener);

}

@BindingAdapter("selectedCountry")
public static void bindCountryValue(AppCompatSpinner pAppCompatSpinner, String newSelectedValue) {
    SpinnerAdapter adapter = pAppCompatSpinner.getAdapter();
    if (adapter instanceof CountrySpinnerAdapter) {
        ((CountrySpinnerAdapter) adapter).bindSelectedValue(pAppCompatSpinner, newSelectedValue);
        return;
    }
    throw new UnsupportedOperationException("The adapter must be a CountrySpinnerAdapter");
}

永远不会调用bindCountryChanged方法。

我也试过这个变种(以下是其他例子):

@BindingAdapter(value = {"selectedCountry", "selectedCountryAttrChanged"}, requireAll = false)
public static void bindCountryValueChanged(AppCompatSpinner pAppCompatSpinner, String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
    AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            newTextAttrChanged.onChange();
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            newTextAttrChanged.onChange();
        }
    };
    pAppCompatSpinner.setOnItemSelectedListener(listener);

}

这被调用,但newTextAttrChanged始终为空。

布局,装订部分:

<data>
    <variable
        name="customer"
        type="my.package.CustomerBinding" />
</data>

小部件:

<android.support.v7.widget.AppCompatSpinner
    android:id="@+id/editCountry"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:spinnerMode="dropdown"
    app:adapter="@{customer.countrySpinnerAdapter}"
    app:selectedCountry="@{customer.country}" />

country我只是ObservableField<String>countrySpinnerAdapter是国家/地区列表的BaseAdapter

Android gradle插件:

classpath 'com.android.tools.build:gradle:2.2.1'

工具版本:

buildToolsVersion "24.0.2"

当然还启用了数据绑定:

dataBinding {
    enabled = true
}

为什么newTextAttrChanged始终为null / BindingAdapter永远不会被标记?我做错了什么?

1 个答案:

答案 0 :(得分:8)

您缺少绑定表达式中的=,以通知系统您希望将此绑定用作双向绑定。

app:selectedCountry="@{customer.country}"

应该是

app:selectedCountry="@={customer.country}"