Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android databinding: BindingAdapter vs InverseBindingAdapter

What is the difference between the two?

When should use one or the other?

When I define a BindingAdapter do I have to create an inverse?

like image 697
Veneet Reddy Avatar asked Aug 12 '17 21:08

Veneet Reddy


1 Answers

Quoting myself, from The Busy Coder's Guide to Android Development:

Two-way binding works well in cases where the way you store the data in the models lines up well with the getters and setters of the associated widget. A boolean field in the model works well with the checked property of a CompoundButton like a Switch, as CompoundButton has an isChecked() method returning a boolean and a setChecked() accepting a boolean.

A BindingAdapter allows you to create other mappings between data types and properties, but only for the classic model->view binding. To accomplish the same thing in the reverse direction, you wind up creating an InverseBindingAdapter. As the name suggests, this serves the same basic role as a BindingAdapter, but in the inverse direction, taking data from the widget and preparing it for the model using custom code. Here, the "preparing it for the model" means converting it into a suitable data type for a setter, Observable field, etc. for your model.

This is fairly unusual.

The example used in some places is "what if I want to tie a float to an EditText?". The InverseBindingAdapter would look something like this:

@InverseBindingAdapter(attribute = "android:text")
public static float getFloat(EditText et) {
  try {
    return(Float.parseFloat(et.getText().toString()));
  }
  catch (NumberFormatException e) {
    return(0.0f); // because, um, what else can we do?
  }
}

The problem is if the user types in something that is not a valid floating-point number, like snicklefritz. parseFloat() will fail with a NumberFormatException. You should let the user know that their data entry was invalid. However, two-way data binding does not support this, with a default value (e.g., 0.0f) being handed to the model instead.

So, to answer your questions:

What is the difference between the two?

BindingAdapter helps populate properties where the data types and View setters are not something that data binding knows how to handle on its own.

InverseBindingAdapter helps populate view-models in two-way binding, where the data types and the View getters are not something that data binding knows how to handle on its own.

When should use one or the other? When I define a BindingAdapter do I have to create an inverse?

Use a BindingAdapter when your desired data type (e.g., a float) is not something that data binding necessarily knows how to fill into a widget property (e.g., android:text on an EditText), but you want to bind it anyway.

If you do that, and you want to do two-way binding, where user changes in the UI automatically update your view-model, most likely you will need a matching InverseBindingAdapter to convert from the property (e.g., text of an EditText) to the desired data type (e.g., a float).

like image 61
CommonsWare Avatar answered Oct 26 '22 23:10

CommonsWare