In previous posts we got an Android application up and running with the Data Binding Library with binding to an
EditText. We also bound a
Button click to a command on the view model.
However, there was a problem with the code that we left in step 3. Did you spot it?
The issue is… if you change the text in the username or password
EditText and then click the Sign In button, the username and password properties on the view model will still have the original string values, not the changed values… Huh, why’s that?
Under the covers, Android data binding is really just code generated by an Android Studio plug-in that connects the view and the view model.
You can examine the generated code here: app/build/intermediates/classes/debug/com/petermajor/databinding/databinding/ActivityLoginBinding.java
That one file contains most of the magic… We’ve already used this class in our activity. Remember this?
In the constructor, the generated code finds all the components that have bindings and puts them into member variables:
Above you can see that inputUsername
EditText is found and put into an appropriate member variable on the binding class. This would be very similar to the code you would normally write in your activity with
The base class for ActivityLoginBinding is android.databinding.ViewDataBinding. That class listens for changes on our observable object (our view model) and passes all notifications to
This method tracks which values have changed by setting “dirty” flags:
At the point where Android decides to update the bindings, it then calls
executeBindings(), which updates bound controls where values are dirty:
The code in ActivityLoginBinding listens for changes in the observable object and propagates the values of dirty fields to the appropriate views.
Notice, however, that there is no generated code that does the opposite - listen for changes in the value of a view and propagate that change to the observable object.
In WPF this type of binding is the default for some views - like
TextView. Because when would a value in a label change and need to be propagated back to the view model? WPF calls this “one-way” data binding and it’s cheap because you only set up a watch in one direction.
WPF also has a concept of “two-way” binding for views where bound values can change, like
EditText. When values in the view change, they can be propagated back to the view model - either on keypress or when the view loses focus, depending on the configuration of the binding.
This type of binding uses more system resources, because it’s watching the value in both locations - view and view model.
It appears that Android does not support two-way binding in this first implementation. I would be interested to hear what offical position is on automatic two-way binding from the team.
In this post, we examined the generated classes that implement the data binding “magic” in the Android Data Binding Library.
This confirmed the “one-way” binding behavior we’re seeing with
In the next post, we’ll finish the view model so that updates in the
EditText will propagate changes back to the view model.