【问题标题】:Android BindingAdapter order of execution?Android BindingAdapter 的执行顺序?
【发布时间】:2016-12-02 13:05:29
【问题描述】:

我需要了解数据绑定库如何确定其 BindingAdapter 的执行顺序。如果我有两个用于视图的 BindingAdapter,并且如果视图具有与这些 BindingAdapter 对应的属性,它将如何确定首先执行哪个适配器?我问是因为执行顺序对我来说很重要。

我有以下 BindingAdapter/s:

public class SpinnerBindingAdapter {

    @BindingAdapter(value = {"entries"})
    public static void setEntries(Spinner spinner, List<? extends SpinnerItem> spinnerItems) {

        for (int i = 0; i < spinnerItems.size(); i++) {
            spinnerItems.get(i).setIndex(i);
        }
        ArrayAdapter<? extends SpinnerItem> adapter =
                new ArrayAdapter<>(spinner.getContext(), R.layout.spinner_item, spinnerItems);
        spinner.setAdapter(adapter);
    }

    @InverseBindingAdapter(attribute = "selectedItem", event = "selectedItemAttrChanged")
    public static Object getSelectedItem(Spinner spinner) {

        Object selectedItem = spinner.getSelectedItem();

        return selectedItem;
    }

    @BindingAdapter(value = {"selectedItem"})
    public static void setSelectedItem(Spinner spinner, SpinnerItem spinnerItem) {
        if (spinner.getAdapter() == null) {
            return;
        }
        // Other code omitted for simplicity
    }

    @BindingAdapter(value = {"selectedItemAttrChanged"}, requireAll = false)
    public static void setOnItemSelectedListener(Spinner spinner, final InverseBindingListener selectedItemChange) {
        if (selectedItemChange == null) {
            spinner.setOnItemSelectedListener(null);
        } else {
            spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    selectedItemChange.onChange();
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }
    }
}

这是我如何填充 Spinner 并设置选择:

<Spinner
    android:id="@+id/spinner_system_activity_edit_tracker_unit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="fill_horizontal"
    app:entries="@{DatabaseModel.queryForAll()}"
    app:selectedItem="@={object.selectedItem}"/>

DatabaseModel.queryForAll 是一个静态方法,它查询数据库并返回一个对象列表,然后将其提供给 BindingAdapter。 BindingAdapter 获取此列表,使用索引更新其每个项目并将其设置为微调器的适配器。

无论出于何种原因,总是首先调用“setSelectedItem”BindingAdapter。这是不可取的,因为我需要先初始化条目。如果它没有首先初始化,那么当第一次调用 setSelectedItem 时 spinner.getAdapter() 将为空。这意味着不会恢复之前保存的选择。

【问题讨论】:

    标签: android android-databinding android-binding-adapter


    【解决方案1】:

    Android 数据绑定中没有保证的执行顺序。因此,您应该合并依赖多个属性的绑定适配器。在您的情况下,您需要合并 selectedItem 和条目的绑定适配器。

    @BindingAdapter(value = {"selectedItem", "entries"}, requireAll = false)
    public static void setSelectedItem(Spinner spinner, SpinnerItem spinnerItem,
            List<? extends SpinnerItem> spinnerItems) {
        // Set entries attribute when provided
        if (spinnerItems != null) {
            for (int i = 0; i < spinnerItems.size(); i++) {
                spinnerItems.get(i).setIndex(i);
            }
            ArrayAdapter<? extends SpinnerItem> adapter =
                new ArrayAdapter<>(spinner.getContext(), R.layout.spinner_item, spinnerItems);
            spinner.setAdapter(adapter);
        }
        // set selectedItem attribute when provided
        if (spinnerItem != null) {
            if (spinner.getAdapter() == null) {
                return;
            }
            // Other code omitted for simplicity
        }
    }
    

    【讨论】:

    • @George Mount 我有一个执行顺序非常重要的要求,我有一个 TextSwitcher,我使用绑定函数设置工厂并设置文本。现在应该先运行 setFactory 绑定方法,然后运行一个 setText 如何实现?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    相关资源
    最近更新 更多