Android Data Binding Library(二):事件处理

Data Binding允许通过写表达式来处理view分发的事件,e.g.onClick。事件属性名通常通过listener方法的名字管理,但存在个别例外。e.g.View.OnLongClickListener有个方法onLongClick(),这时事件的属性名是android:onLongClick。
有两种方法来处理事件

  • 方法引用Method Reference
    在表达式中,可以引用符合监听器中方法签名的方法。
  • 监听器绑定Listener Bindings
    使用lambda表达式,当事件发生时,对这些lambda表达式进行计算。

方法引用

官方说明:In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead.

事件和处理方法可被直接绑定,这和android:onClick能被Activity中方法赋值类似。方法引用相比View#onClick属性的主要优点是表达式在编译时处理,如果方法不存在或者签名不对,你将会收到一个编译错误。
方法引用和监听器绑定之间的主要区别是前者在数据绑定时创建真正的监听器实现,而不是事件被触发时。如果你倾向与事件发生时计算表达式,请使用监听器绑定方法。
To assign an event to its handler, use a normal binding expression, with the value being the method name to call. For example, if your data object has two methods:
事件处理方法示例:

public class MyHandlers {
    public void onClickFriend(View view) { ... }
}

布局文件中对点击事件监听器赋值的表达式如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.MyHandlers"/>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
           android:onClick="@{handlers::onClickFriend}"/>
   </LinearLayout>
</layout>

注意:表达式中方法的签名必须和监听器对象中的方法签名完全保持一致。

在Activity文件中创建绑定关系,可以看到需要设置布局文件中定义的两个variable:user和handlers

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        ActivityMain2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_main2);
        User user = new User("Test", "User");
        binding.setUser(user);
        binding.setHandlers(new MyHandlers());
    }

监听器绑定

官方说明:These are lambda expressions that are evaluated when the event happens. Data Binding always creates a listener, which it sets on the view. When the event is dispatched, the listener evaluates the lambda expression.
Listener Bindings are binding expressions that run when an event happens. They are similar to method references, but they let you run arbitrary data binding expressions. This feature is available with Android Gradle Plugin for Gradle version 2.0 and later.

在方法引用事件处理中,方法的参数必须和事件监听器的一致。而在监听器绑定事件处理中,只要求返回值和监听器的保持一致,除非监听器返回空。示例:

public class Presenter {
    public void onSaveClick(Task task){}
}

绑定点击事件方法示例:

<?xml version="1.0" encoding="utf-8"?>
  <layout xmlns:android="http://schemas.android.com/apk/res/android">
      <data>
          <variable name="task" type="com.android.example.Task" />
          <variable name="presenter" type="com.android.example.Presenter" />
      </data>
      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
          android:onClick="@{() -> presenter.onSaveClick(task)}" />
      </LinearLayout>
  </layout>

监听器使用lambda表达式,只能作为表达式的根元素。当在表达式中使用回调时,Data Binding自动创建必要的监听器并注册事件。当view触发事件时,Data Binding对表达式进行求值。

As in regular binding expressions, you still get the null and thread safety of Data Binding while these listener expressions are being evaluated.

上例中并未定义点击onClick(android.view.View)中传入的view参数。关于监听器参数,有两种选择:一忽略所有的参数;二命名所有参数。如果选择命名这些参数,则可以在表达式中使用。上述表达式也可以写为:

android:onClick="@{(view) -> presenter.onSaveClick(task)}"

如果想在表达式中使用参数,方法如下:

public class Presenter {
    public void onSaveClick(View view, Task task){}
}
 android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"

lamda表达式可以有多个参数。

public class Presenter {
    public void onCompletedChanged(Task task, boolean completed){}
}
//监听事件原型 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />

如果监听的事件返回值不是空,则表达式中需要返回一样的类型。例如监听长按事件时,需要返回false。

public class Presenter {
    public boolean onLongClick(View view, Task task){} 
}
//监听事件原型 boolean onLongClick(View var1)
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"

如果因为null对象导致表达式不能求值,Data Binding返回java中该类型的默认值。e.g. 引用类型返回null,int返回0,boolean返回false,etc.
如果需要使用表达式做判断(如三元组),void可以用来作为一个符号。

android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
避免使用复杂的监听器

监听器表达式功能很强大,并让代码更易读。但是,监听器如果使用复杂的表达式会使得布局文件很难阅读和难以维护。这些表达式应该尽量简单,只承担将可用数据从UI传递到回调函数的作用。任何商业逻辑的实现,都应该放在表达式中触发的回调函数中。

参考文档:https://developer.android.google.cn/topic/libraries/data-binding/index.html#build_environment

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容