Android Architecture Components – Looking at Room and LiveData – Part 1

This week at Google I/O 2017, there were a lot of new announcements for the Android Platform. One of the announcements was the new architecture guidelines for Android! This is a welcome addition to the Android platform.

Previously the Android team refrained from giving advice as to how you should structure your Android applications. For the most part this meant that anyone learning Android for the first time would just end up placing all their code into the Activity files and occasionally moving stuff into an AsyncTask if the app crashed with a NetworkOnMainThreadException. Only after trying to add unit tests and instrumentation tests would you really understand that your code you have just spent so long developing was not easy to read, make changes to or to write tests for. Continue reading Android Architecture Components – Looking at Room and LiveData – Part 1

Android Data Binding – Part 2

In Part 1 I gave an introduction into the Android Data Binding Library. I suggest reading that post first before reading further.

In this post I am going to discuss the following :

  • Binding Adapters
  • Binding Events
  • Two Way Binding

Binding Adapters

Creating an adapter and using Android Data Binding for each item is quite simple. Below is an example of how your RecyclerView adapter will look after using Data Binding:

  1. The first difference in this method is that our ViewHolder  object now only contains a ViewDataBinding  object (instead of ImageViews and TextViews)  and a method to get the binding object.
  2. The method onBindViewHolder binds the view to the item variables. This is shown by the lines holder.getBinding().setVariable(BR.book, bookDetail) . This sets the views book variable defined in the layout XML.
  3. The method holder.getBinding().executePendingBindings()  triggers the View to be updated with the new values provided. This method has to be run on the UI thread.
  4. Within our list_item_book.xml  layout file we define and access variables in the same way as in Part 1. With the <data> section defining all the variables to use in the xml, including the imports. The Views then contain reference to those objects. For example  android:text="@{book.bookTitle}"  accesses the books title and assigns the value to the text of the TextView.

Events

In the same way that we bind variables in XML, we can set variables for click listeners in XML.

  1.  Create the click listener in code:

2. In list_item_book.xml, define the View.OnClickListener  and set the View that the click should fire on by using the variable defined android:onClick="@{click_listener}" . This will then trigger the click event.

3. In the adapter, set the click listener:

I ran into an issue whilst trying to set the Views Tag in XML due to a bug in the Android Data Binding Library (they did warn us it’s in beta 🙂 )

The following XML causes an issue with the Data Binding Library that will cause your app to not compile:

An explanation from StackOverflow as to why this wont work:

” When targeting devices pre-ICS, Android data binding takes over the tag of the outermost element of the layout. This tag is used for mostly for binding lifecycle and is used by DataBindingUtil.findBinding()  and DataBindingUtil.getBinding() . “

Following the advice from the post and because I am targeting ICS and above,  I used the mechanism specified in the answer:

Create a BindingAdapter to set the tag after the binding has occurred:

Then in the XML, I can easily attach any object onto the View:

When the item is clicked we can get more information about the item by using the  view.getTag()  mechanism.

Two Way Binding

This is where things get tricky as the library does not work as expected. Unfortunately, binding an EditText to a String field in an object doesn’t yield the results we would hope for.

The following is a way to get two way binding working:

  1. In our BookDetail object we create an ObservableField<String>  that will contain the books title. This will then inform anything that is watching of variable changes.
  2. In our XML, we will bind to that field on both the EditText and the TextView.
  3. We need to create a TextWatcher which will update the String field when the user types. It will notify the TextView of the changes.

As you can see this is not an ideal solution. Firstly a lot of boiler plate code is required to get it to work and it’s not very elegant.

Better Solution

Fabio Collini has a great detailed post with his solution to this problem – by creating a custom binding for the property. In a few simple steps:

  1. Create a custom BindableString  object
  2. To get the text out of the BindableString  object, we need to have a binding conversion. This instructs views on how to convert a BindableString into a String object:
  3. Create a custom BindingAdapter to handle the text watching and setting:
  4. Set the bindable string in XML.
  5. Change the BookDetail object to use a BindableString instead of the ObservableField<String>

6. Two way binding should now work within your app.

Final Verdict

The Data Binding Library is a powerful tool. I suspect it will become more useful and more widely adopted. For now though, there are a few bugs and some kinks that need to be ironed out.  After experimenting with it for a while, I am excited for what the library could potentially do in the future.

What are your thoughts on this library? Have you used it yet? Leave a comment below!

 

Getting Started: The Android Data Binding Library Part 1

Anyone who has dabbled a bit in Android Development will know that Android is lacking a key component of MVVM: The ability to bind data without a couple of lines of code. 

For instance, setting a TextView to some value retrieved from a server is pretty complex, considering the simplicity of the task:

Doing everything this way can become a bit cumbersome and leads to very cluttered code. I don’t think anyone needs much convincing that this process of manually binding data is not ideal.

Cue: Android Data Binding Library (It’s like someone heard our cries? :-)). The 6 lines above can be converted into 2:

I decided to take a look and try it out, and see how well it would work for my applications.

Initial Impressions:

  • Very powerful library 
  • Less cluttered code
  • Less view logic in Activity and Fragment classes (yay!?!)
  • Compatible from API version 7+ (2.1)
  • Not recommended for use in production yet (It’s currently in Public Beta Phase but you are welcome to ship your app using it, it’s just not advised)
  • No support in Android Studio for syntax highlighting or code completion 

How to get started with the Android Data Binding Library:

  1. To get started with the Data Binding Framework, you need to include a couple of Gradle Dependencies in your top level build.gradle file in the dependencies section:

     
  2. In the Top Level build.gradle make sure the following is defined (It probably is already):
  3. In each module of your project make sure to include the following right after the android plugin is applied:
  4. Create your object that you wish to represent in your view. In our case we have a Page object which contains a number, image link and some text.
  5. Create Layout XML as per usual.  We have a ImageView  and a TextView  in our layout. At the start of the layout we will define what objects and methods will be used in this page.

    Let’s go through the new changes in this XML:

    • As you can see we no longer use a LinearLayout as the start tag, instead we use <layout> with the namespace declarations.
    • There is now a <data> section at the top of the file, which will include your imports to the different libraries you require. In this case, I required the TextUtils class. You can access any static methods define in a class. In this example I use the method TextUtils.isEmpty() to do different view logic.
    • <variable> tag defined, this allows you to define objects within the XML that will be used on the View itself.
    • Accessing a variable and some of its properties is simple:

    The words @{page2.htmlText}  will run the method getHtmlText()  on the page object.  One thing to note: Android Studio looks as if the method getHtmlText()  is unused, since it hasn’t found the usage in the XML but after deleting it, the project will fail to compile.

  6. After creating the Page object and the XML that will use the object, how do we go about putting the two together? Android will generate the object FragmentPageBinding (this name will change depending on your layout, eg. activity_book.xml  will create the object ActivityBookBinding ) which contains all the objects that you define in the <data> section of your corresponding XML file. From then, you just set the variables and your view will contain the correct values. As you can see, no view logic is sitting in my Fragment or Activity. Yay!

  7. In the above code, you may also notice that on the ImageView we have the attribute  app:imageUrl="@{page.image}" . I like to load images from the web, in a background thread – using a library like Glide or Picasso . Create a Utils class called BindingUtils and pop this method in there. Now your ImageView will call this section of code with the url that we passed to it. We can then do what we like with it. In this case, we load the image into the view.

In Part 2 we will look at Two Way Binding and Binding Adapters.