Develop your application faster & smarter with Data Binding — Binding Adapters — Part 5

Harin Trivedi
AndroidPub
Published in
4 min readMay 2, 2017

Hello everyone👋🏼, you might have looked into Part 4 of data binding and learned about Observable Objects. Using them, it will make the data handling very easy and robust where you do not need to worry about presentation logic, which is separated and just focus on your core logic.

There is even more advance functionality given to manage above thing with the ability to operate on data more deeply! You might also be thinking what is still left in data binding so far?!

Attribute Setters:

Whenever a bound value changes, the generated binding class must call a setter method on the View with the binding expression. The data binding framework has ways to customize which method to call to set the value.

ref:http://giphy.com

Let’s derive the understanding. As you already know that whenever you access values of any property via binding, it uses the getter method of related property. Also when using observables, it also needs getter-setter methods to make it work. Not what if we can implement our own setter based our requirement!? Yes, that’s what Attribute Setter is all about.

Custom Setters:

The other types are Automatic and Renamed settres, but that is not the point of interest here. Custom setters are useful for adding added function to the view which will do job for you. It’s similar like defining an attribute for a custom view. Let’s see with a simple example.

public class CommonBindingUtils {
@BindingAdapter("android:text")

public static void setText(TextView view, String text) {
view.setText(text+"123");
}
}

BindingAdapter annotation allows to customize how a setter for an attribute is called.

Above example will add “123” after static string passed with attribute android:text used anywhere in layout! (in whole app of course). Surprising, right! But you may not want to modify setter for system defined attributes (eg. android:text), that’s really BAD IDEA.

But, you can define your own attribute which will do job for you. Let’s modify our setter and add custom attribute ‘greetings’.

@BindingAdapter("greetings")
public static void setName(TextView view, String text) {
view.setText("Welcome, " + text);
}
...
app:greetings="@{name}" // name is passed as binding variable

This will directly show “Welcome, Name” in text view! Great job… Now let’s see my favorite example of custom setter where I will try to load image from a url into image view using Glide.

@BindingAdapter(value = {"imageUrl", "placeholder"}, requireAll = false)
public static void setImageUrl(ImageView imageView, String imageUrl, Drawable placeholder) {
BitmapTypeRequest<String> target =
Glide.with(App.getInstance().getApplicationContext()).load(imageUrl != null ? imageUrl : null).asBitmap();
if (placeholder != null) {
target.placeholder(placeholder).error(placeholder);
target.into(imageView);
}
}
...
<ImageView
app:imageUrl="@{user.picUrl}"
app:placeholder="@{@drawable/ic_profile}"
/>

This will load the image from the url into ImageView directly, also this setter can be used anywhere with image view in your project. This way you can also add multiple attributes in Binding Adapter, but they should match the arguments with same sequence defined in the method’.

Let’s see another example, where we will try to set age of the user from the date of birth value.

@BindingAdapter("age")
public static void setAge(TextView textView, String dob) {
try {
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
Calendar today = Calendar.getInstance();
Calendar dobCal = Calendar.getInstance();
dobCal.setTime(format.parse(dob));

int age = today.get(Calendar.YEAR) - dobCal.get(Calendar.YEAR);
if (today.get(Calendar.DAY_OF_YEAR) < dobCal.get(Calendar.DAY_OF_YEAR) && age > 0) {
age--;
}

textView.setText(String.valueOf(age));
} catch (Exception ignored) {
}
}
...
//In layout
<TextView
android:id="@+id/tvAge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:age="@{user.dob}" /> //value of dob = "01-01-1991"

That will show age in text view. If I try to extend this setter to actually hide the view if the age of user is below 18! So there is ‘n number’ possibilities you an use custom attribute setter as per your requirement. Before we were writing the logic inside ui, which was not good practice for readability so now using setter, we can separate the logic from the ui part with even more flexible view. Pretty awesome, Right !!!!!

ref:giphy.com

Checkout full Demo code on github. Thanks for going through all parts of this series. I hope you might have learned and explored things which may help you a lot. Please post any queries or suggestions from your side 👍🏼

Links for previous parts: Part1, Part2, Part3, Part4.

If you enjoy reading you can also visit my other blog posts:

--

--

Harin Trivedi
AndroidPub

Software Engineer, Exploring the world of Technology!