Don’t let BindingAdapters kill CustomViews!

What are BindingAdapters?

Google introduced the DataBinding library. It is a great project which eliminates dependencies like ButterKnife and couples directly your View  model with the GUI you are building. They also introduced the concept of the BindingAdapters. You can put a public static method with an annotation anywhere in your classes. Preferably, most of these methods will be in a single place like this:

 

@BindingAdapter({"app:click", "android:clickable"})
 public static void setOnClick(TextView view, View.OnClickListener clickListener,
                               boolean clickable) {
     view.setOnClickListener(clickListener);
     view.setClickable(clickable);
 }

So if you put app:click in your layout file on a TextView object, this method will always get called. So you can have something like:

<TextView
  app:click="@{listener}"
  ... />

This gives you great flexibility. You can attach custom XML layout attributes to any element and get this binding adapter called.

Practical examples

  1. No more CustomTextView – you can just bind to “app:font” and set the custom font
  2. Load images from web directly into ImageView – pass the url to “app:imageUrl” for example and let Picasso load the image
  3. Attach DatePickers to EditTexts – have an attribute called “app:datePicker” and just call a DatePicker which sets the value to the EditText
  4. Format money text
  5. Display progress bar

    And many many more.

So what is the problem?

Well, it is simple. You can really easily tend to move everything to a huge class with static methods called BindingAdapters. It is useful, but there are some cases where you will be wondering how the fuck this magic works? Then you go to the view class you are currently using, then you go to the BindingAdapters just to see that someone move it to a very strange location. So I think this is the place where BindingAdapters clash with custom views. A custom view is an object, with it’s own behavior and state. It doesn’t need a public static method to tell it how to set it’s drawable padding for example. It does not need someone else to tell it how to resize it’s height or to make a drawing magic listening to it’s view tree observer from a public static method. This is so against OOP that it is hard for me to explain how much exactly.

Use it with precaution

If you have an ImageView with an icon and a counter at the top right you don’t need to create a binding adapter for that. Like passing “app:counter” won’t make your view more useful. How about if you extend the ImageView and make a class called RequiredActionsImageView or something else. And then you include it in your code . How about that? Sound better and you know what to expect from it. isn’t telling you anything about the behavior of the ImageView. And the next thing you will have to do is find the binding adapter method for it.

Final

Not every time the easiest way is the smartest one. It may save you time in the short run, but it also may take you much more time in the long one. Custom views are there and are still unused. You just need not be afraid.

You may also like...