数据绑定:使用多个方法绑定来自侦听器的单个方法

Databinding: Bind single method from listener with multiple methods

AndroidUI Toolkit 团队的 Yigit Boyar 和 George Mount 成员给出了 talk on databinding。在 13:41 的视频中,George Mount 说了这个

You can also do some of the weird listeners, like onTextChanged. TextWatcher has three methods on it, but everybody only cares about onTextChanged, right? You can actually access just one of them if you want, or all of them."

<Button android:onTextChanged="@{handlers.textChanged}" …/>

他似乎是在说,而不是使用通常的 addTextChangedListener 看起来像这样的方法

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        //Do something
    }

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

我们可以简单地这样做

<EditText 
    android:onTextChanged="@{handlers::onTextChanged}"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

处理程序class

public class Handlers{
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        //Do something
    }
}

该代码在此实例中有效,但在侦听器具有多个方法(如 ViewPager 的 addOnPageChangeListener 方法)的其他情况下似乎无效。例如这不起作用

<android.support.v4.view.ViewPager
    android:OnPageSelected="@{handlers::onPageSelected}"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

和处理程序class

public class Handlers{
    public void onPageSelected(int position) {
        //Do something
    }
}

该项目在尝试构建时吐出此错误

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Could not resolve handlers::onPageSelected as a listener.

****\ data binding error ****

我现在有点困惑,因为事实证明 EditText 实际上有一个继承的 onTextChanged 数据绑定库也可以绑定 android:onTextChanged="@{handlers::onTextChanged}" 的方法。

所以我的问题是,实际上是否可以绑定到单个侦听器方法,而我遗漏了一些东西,或者 George Mount 在他的演讲中是否犯了错误?

但愿这不是谈话中的错误:-)

看来我们没有为 ViewPager 实现它。实施起来并不太困难。有一个技巧 -- 您必须为每个匹配方法声明一个接口。

public interface OnPageScrollStateChanged {
    void onPageScrollStateChanged(int state);
}
public interface OnPageScrolled {
    void onPageScrolled(int position, float offset, int offsetPixels);
}
public interface OnPageSelected {
    void onPageSelected(int position);
}

然后应该为事件创建绑定适配器:

@BindingAdapter(value = {"android:onPageScrollStateChanged",
                         "android:onPageScrolled",
                         "android:onPageSelected"}, requireAll=false)
public static void setViewPagerListeners(ViewPager view,
        final OnPageScrollStateChanged scrollStateChanged,
        final OnPageScrolled scrolled,
        final OnPageSelected selected) {
    OnPageChangeListener newListener = null;
    if (scrollStateChanged != null || scrolled != null || selected != null) {
        newListener = new OnPageChangeListener() {
            @Override
            public void onPageScrollStateChanged(int state) {
                if (scrollStateChanged != null) {
                    scrollStateChanged.onPageScrollStateChanged(state);
                }
            }
            // similar with the other two methods ...
        };
    }

    OnPageChangeListener oldListener = ListenerUtil.trackListener(view,
        newListener, R.id.viewPagerListener);
    if (oldListener != null) {
        view.removeOnPageChangeListener(oldListener);
    }
    if (newListener != null) {
        view.addOnPageChangeListener(newListener);
    }
}