Develop your application faster & smarter with Data Binding — Event Binding — Part 2

Harin Trivedi
AndroidPub
Published in
5 min readMay 2, 2017

Hello everyone👋🏼, you might have looked into introductory Part 1 of data binding and got some idea about integration and basic usage. Fine, now you might be thinking “What about events?”, Right? After binding data you would like to bind actions to operate on data or perform your own actions.

There are two types of event handling, According to the documentation:

Method References: 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 the 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.

Listener Bindings: 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.

Ohhh!, That’s lots of theory. Let’s try to understand it with some sample lines of code.

  1. Method Reference: A method can be referenced directly to event associated with any component eg. onClick(). Here the method will have a similar definition like the event. For example, if you are trying to bind on click event with any method let’s say onHandleClick() you must define it like this,
public class EventHandler {
public void onHandleClick(View view) {... }
}

EventHandler class implements a method onHandleClick() which contains an argument instance of View. As, onClick method also has an instance of View class, both definitions are not matching. Now you can reference it directly by using the referencing expression as below.

<data>
<variable name="handler" type="com.example.EventHandler"/>
<variable name="user" type="com.example.User"/>
</data>
...<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android: text="@ {user.firstName}"
android:onClick="@{handlers::onHandleClick}"/>

You need to pass an instance of EventHandler class like binding.setHandler() from activity. Method reference expressions are processed at compile time, so if the method does not exist or its signature is not correct, you receive a compile time error.

In my demo, to simplify it, I have passed instance of View.onClickListener() directly in the layout, and attached to the on click event, where you do not need to make separate class for event handling and you can refer onClick() method easily.

<data>
<variable
name="listener"
type="android.view.View.OnClickListener" />
</data>
...<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android: text="@ {user.firstName}"
android:onClick="@{listener::onClick}"/>

Now just implement OnClickListener interface in activity as we normally do, and pass it through the binding object. Similar way you can also refer other events like onLongClick, onCheckedChanged and so on.

2. Listener Binding: Now what if I want to bind any method on a particular event on a component? My method could have any kind of definition which may not match with event method, and even I want to pass data though method. Let’s see how to achieve this.

public class Presenter {
public void onSaveProfile(User user){}
}

And in your layout file,

<data>
<variable name="presenter" type="com.example.Presenter"/>
<variable name="user" type="com.example.User"/>
</data>
...<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android: text="Save"
android:onClick="@{() -> presenter.onSaveProfile(user)}"/>

This seems familiar, isn’t it? Yes, I you have referred lamda expressions in java8, data binding is achieving listener binding in a similar manner. Here You may user any method from the Presenter class, as you can see an instance of the user class is also passed as an argument of it. I hope it makes sense!

This approach is super useful when you have adopted MVP-Model View Presenter approach. Where your presenter class implements methods to call data access methods. I will recommend you to go through this Blog which explains MVP in brief.

The major difference between Method References and Listener Bindings is that the actual listener implementation is created when the data is bound, not when the event is triggered. If you prefer to evaluate the expression when the event happens, you should use listener binding

“Question 1: What if I want to access view on which I attached listener binding?”

Yes, you can. For that mention instance of the view in the expression and same way an argument in your method.

public class Presenter {
public void onSaverofile(View view, User user){}
}
...android:onClick="@{(view) -> presenter.onSaveProfile(view, user)}"

“Question 2: What if my method, which I attached to event binding, returns a value?”

You can not access returned values in case of event handling. It’s same as when you defined click event you won’t be able to return anything. But yes, if you want to pass an instance of any callback class implementation, that you can pass as an argument in the expression. But as per documentation,

If the event you are listening to returns a value whose type is not void, your expressions must return the same type of value.

“Question 3: Can you give me more example on event binding?”

public class Presenter {
public boolean showInfo(User user){}
public void onFollow(User user){}
}
...<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android: text="Show Info"
android:onLongClick="@{() -> presenter.showInfo(user)}"
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{(cb, isChecked) -> presenter.onFollow(isChecked)}" />

--

--

Harin Trivedi
AndroidPub

Software Engineer, Exploring the world of Technology!