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

Posted

技术标签:

【中文标题】数据绑定:将来自侦听器的单个方法与多个方法绑定【英文标题】:Databinding: Bind single method from listener with multiple methods 【发布时间】:2017-01-06 16:17:26 【问题描述】:

android UI Toolkit 团队的 Yigit Boyar 和 George Mount 成员提供了talk on databinding。在 13:41 的视频中,George Mount 这么说

你也可以做一些奇怪的监听器,比如 onTextChanged。 TextWatcher上面有3个方法,但大家只关心 onTextChanged,对吧? 您实际上只能访问其中一个,如果您 想要,或者全部。"

<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_
    android:layout_/>

处理程序类

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_
    android:layout_/>

和 Handlers 类

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 在他的演讲中犯了错误?

【问题讨论】:

【参考方案1】:

希望这不是谈话中的错误:-)

看起来我们没有为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);
    

【讨论】:

太棒了!直接从马的嘴里回答:) 什么是 R.id.viewPagerListener?

以上是关于数据绑定:将来自侦听器的单个方法与多个方法绑定的主要内容,如果未能解决你的问题,请参考以下文章

将多个类的数据绑定到单个列表视图/xamarin 表单

Linux系统下多网卡绑定操作方法

是否可以将事件侦听器绑定到来自外部脚本的影子 dom 内的元素?

Win10系列:JavaScript 数据绑定

当条件多个布局应用于单个活动时管理单个数据绑定对象

props单个数据绑定和多个数据绑定+vue默认插槽的基本使用+具名插槽的写法(2种)