Posted on

Write less with Android Data Binding

Write less with Android Data Binding

Hey there, in my previous post we looked at the main two approaches with Data Binding. While first approach was very familiar to us, but after a while you get bored of it and want something more fancy.  How to actually write the next level progressive code with Data Binding? In this post we’ll find out is it worth to actually learn how to use Data Binding. And most of all, can you write less with it and get results faster. So let’s get started.

Image Loading

I expect all of you have used Glide or Picasso for loading and caching images on Android. And what you were doing before is calling this line every time to load an image

And if you practice some of the D.R.Y. principles you could’ve come up with some method like this

and call it from any of your classes, basically this already fine, isn’t it? So can Data Binding actually help us write less code? This guide shows us that it’s possible to move the logic from Java code to XML using custom Binding Adapters and XML attributes. For example Data Binding image loading approach would be to create this adapter

and add an imageUrl attribute to any of desired ImageView’s.

Assume we have a Movie variable declared in our layout. As you see we declared Binding Adapter for app namespace, but ImageView attribute has a different one. App namespace is ignored unless it’s android namespace, you can create Binding Adapter and declare attributes with different namespaces, ‘just works’ like says Neto Marin says.

Image Placeholders

But Ihor, what if I have a placeholder or onFinishListener I want to use? No problem with that, just declare Binding Adapter like this

and add extra attribute to you ImageView

Now unfortunately you cannot use the same Adapter method for ImageView’s with and without placeholder. For example there’s some ImageView’s that you want to use placeholder for and others not, with Adapter above you won’t be able to build if you don’t declare two of those attributes each time on ImageViews. So we’ll have to write overloaded Binding Adapter with one attribute, then we’ll be able to handle images with and without placeholders.

Load Callbacks

So what about onFinishLoadListeners? Glide has a RequestListener, using the same approach we add a new attribute – loadListener, a new overloaded method, so as you see for each custom set of attributes we’ll have to write a separate Binding Adapter. That’s what I got

And XML code

In this approach I declared listener as a variable in layout and set it in Java code. Once again if you not familiar with Data Binding basics you can read first part of my previous post. The second approach would be to have RequestListener declared as a field in Movie model and access listener in ImageView from movie model. First approach makes more sense to me though.

So now I assume you figured that we can handle image loading completely with Data Binding library, the main thing in here is that it’s moves your code logic from completely Java to partially XML, partially Java. And you might want to ask me, isn’t this post called ‘Write less code’, not ‘How to monkey move your code from one place to another’? And actually we ended up writing more code, I bet you could just write few Glide chains and be happy. I totally get you! Now what am I going to do about that? Guys, the only solution that I came up with to write less code with Data Binding is… Create an Android Library!

Here’s the secret

If you’ve never created a Java or Android Library, I will make a tutorial in a while so stay tuned. Now back to work. So library makes much more sense that writing bunch of those Binding Adapters for each new project you create, right? Just to handle image loading you’ll need about 4-5 different methods. And there’s nothing better then creating own library for your use.

With libraries there three approaches. First is to have it as a module. Second to add a jar library to project lib folder. Third to upload it to BinTray and simply paste one compile line to build.gradle. Yes, third way is more attractive isn’t it? I uploaded my library to BinTray and now I just add one line of code

and Bingo! it works. Amazing, now that’s the way to go, add this one line to build.gradle, and you have app:imageUrl, app:placeholder, app:loadListener ImageView attributes available anywhere you want! I really like it and going to use it everywhere. I can extend DataBinding adapters further and THIS is actually how you can write less with Data Binding. Fell free to try this library, Pull Requests are welcome.

Fragment events

How often do you use android:onClick View attribute? I like it so much, way easier than setting listener in Java and it looks cleaner. You just create a method in you Activity with an action name. But hold on, you cannot declare this method in Fragments. For example I have a Fragment and I want onClick attribute on some View to call a method declared in this Fragment, doen’t work this way, only for Activities. That’s a pity, but with Data Binding we can fix that.

Data Binding has event handlers, what you do is declare a handler as a variable in layout, set it in Java and you call methods any methods from your handler and this handler class is going to be our Fragment.

Set onClick attribute

Parameters in this lambda expression depend on your method parameters of course. And set layout variable in Java

Create as many onClickListeners in your fragments as you want now. And if you read my previous post then you know how to make your Fragments have that layout variable set by default and have the Java part as well!

Check out this updated repo where I use my library for Binding Adapters and Fragment onClickListeners.

Hope you find it useful, if so – let me know in comments. And don’t forget to subscribe and receive updates from My Hexaville!