Develop your application faster & smarter with Data Binding — Observables — Part 4

Harin Trivedi
AndroidPub
Published in
6 min readMay 2, 2017

Hello everyone👋🏼, you might have looked into Part 3 of data binding and learned about expressions and using references. Today we will explore a cool feature provided by data binding which will literally make you feel amazing! That is Observables …..….

Any plain old Java object (POJO) may be used for data binding, but modifying a POJO will not cause the UI to update. The real power of data binding can be used by giving your data objects the ability to notify when data changes.

That means, whenever any data changes it will notify us where to reflect this change in your layout or vice versa. That seems interesting, Right?!! So, there are three different data change notification mechanisms:

  • Observable objects
  • Observable fields
  • Observable collections.

As per the documentation:

The Observable interface has a mechanism to add and remove listeners, but notifying is up to the developer. To make development easier, a base class, BaseObservable, was created to implement the listener registration mechanism. The data class implementer is still responsible for notifying when the properties change. This is done by assigning a Bindable annotation to the getter and notifying in the setter

Let’s modify our User class to implement BaseObservable.

private class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}

If you can see, @Binable annotation is given to each property which you want to be observed. What is the meaning of this?

  • Let’s assume a use case. There is one function which is modifying properties of User class. Also we have passed the same instance as a binding variable inside the layout. So in normal flow, when any property is changed, you will manually set the updated value inside the layout. Correct. Now what if you implement it via Observables? By any means, when any of the property is changed by calling its setter method let’s say setFirstName() your binding will be notified directly and the value in TextView, where first name is displayed, will automatically change!!!! Yes, that’s what observable does.
  • The Bindable annotation generates an entry in the BR class file during compilation. So it will contain references to all property annotated with @Bindable. It’s same like the R class file which is auto-generated for all ids inside your layout, or references.
  • So, this line is important if you want to notify any changes in a property inside your model class.
notifyPropertyChanged();

We just saw an example of Observable Object, where you need to write code for which field you want to be observed and from where to notify. If you had gone through the Demo on github, You would have noticed that AttractionModel.java class implements observable functionality.

Now save development time, ready made properties are provided which implements observable functionality, where do not need to add bindable annotation or notify any change. These are ObservableFields and ObservableCollections.

  1. ObservableFields:

Above are the types, which you can use instead of a primitive type, inside your model class. So when value of these properties will change, its binding will automatically get notified. Let’s see how to use them.

private lass User {
public final ObservableField<String> firstName =
new ObservableField<>();
public final ObservableField<String> lastName =
new ObservableField<>();
public final ObservableInt age =
new ObservableInt();
public final ObservableFloat height =
new ObservableFloat();
public final ObservableBoolean isChild =
new ObservableBoolean();
}

Here, firstName and lastName having string types, defined with ObservableField<String> type. This is an example of general ObservableField which allows to define a generic type with observable field. Others are the example of specific observable type. You can use them like,

//set value, this will notify accosiated bindings.
user.firstName.set("First name");
user.lastName.set("Last name");
user.age.set(25);
user.height.set(90.0f);
user.isChild.set(false);
//get value
String age = user.firstName.get();
String age = user.lastName.get();
int age = user.age.get();
float age = user.height.get();
boolean age = user.isChild.get();

2. ObservableCollections:

It extends the same concept of ObservableField for the collections types. There, two types are provided ObservableArrayList and ObservableArrayMap. You can read more about them in DataObjects-developer.android in detail.

MVVM approach with Observables

I am interested in discussing about MVVM (Model-View-View-Model) approach. For just understanding,

MVVM facilitates a separation of development of the graphical user interface. MVVM represents an architecture that communicates from Model to View and from View to Model. So unlike the MVP pattern, it removes presenter part and simplifies communications of data…

MVVM diagram

With data binding you can easily implement this approach in your project. Let’s understand this by an example. Let’s consider the User class we used in in starting, we will remove bindable annotation from it.

(Usecase: A user is marking one or multiple user from list of followres/friends.)

public class User {
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

Now let’s create another class which will act as a mediator which will hold an instance of user class and helper methods to 1.access property of user class and 2.notify observers based of values.

public UserViewModel extends BaseObservable {
private User user;

public UserViewModel(User user) {
this.user = user;
}

public void setFavourite(boolean isFav) {
user.setFavourite(isFav);
notifyPropertyChanged(BR.favouriteVisibility);
}

@Bindable
public int getFavouriteVisibility() {
return user.isFavourite()?View.VISIBLE:View.GONE;
}

}

In layout file we will pass the UserViewModel.

<data>
<variable
name="viewModel"
type="com.example.UserViewModel" />
...
<ImageView
android:id="@+id/imgFav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{viewModel.favouriteVisibility}"
app:srcCompat="@drawable/ic_fav" />

Not when I will call setFavourite() method from an action to toggle favorite attribute, the visibility of ImageView will get changed.

//To mark as favorite
viewModel.setFavourite(true);
//To mark as not favorite
viewModel.setFavourite(false);
-- Both notifies change to 'favouriteVisibility'

So communication follows the path as View-ViewModel-User(Model). Here any property of User class is not accessible to outside view, but View wants to access property of interest which is favouriteVisibility which can be accessed only through the UserViewModel class, which can only access the uesr instance! I hope, it gave you understanding about MVVM approach. I will ViewModel class in demo code for reference.

ref:https://giphy.com

--

--

Harin Trivedi
AndroidPub

Software Engineer, Exploring the world of Technology!