Approaching Android with MVVM
Joe Birch

Great article, though your view model doesn’t need to extend BaseObservable as it’s essentially immutable.

You have a few options with data binding when it comes to view models.

If your views model changes (based on updates from the model or actions from the view), you have 3 main choices:

  1. Expose the properties as ObservableField/Booleans/whatever from the library that extends BaseObservable, and make them public finals. This is the quickest way but not necessarily the best as it exposes a getter and setter for each property that the view can read or write to; even if it’s only intended to be used for reading it’s not explicit. Also BaseObservable holds a lot for what it is (look into ChangeRegistry) , multiplied by all the properties in your view model, multiplied by all the items in your list (if it’s in a list) results in potentially a lot more memory consumption then you anticipated, yea that magic ObservableBoolean comes at a cost.
  2. Extend BaseObservable yourself resulting in a single ChangeRegistry under the hood (instead of one per property), and expose your properties with getters annotated with @Bindable, once the backing field is set you must manually notify attached listeners (the generated ViewDataBindings) with notifyPropertyChanged. This downside of this method is that, well.. inheritance and more verbose.
  3. Implement the Observable interface yourself and either copy what BaseObservable does directly (looks a bit dirty in your view model) or implement it and delegate the calls to an injected implementation that contains a ChangeRegistry , with Kotlin you can keep this even cleaner by using the interface delegation. This method is the most verbose way, but the most flexible and better for testing.

More info here:

If your view model changes and is used in a RecyclerView I’d go with option 3. You may want to funnel property changes to the RecyclerView adapter’s onBind callback if you want to take advantage of the ItemAnimator. When a property change notifies the view outside of this callback you will get no animation from the ItemAnimator.

Also for click actions it is cleaner to use “@{() -> viewModel.doAction()}” notation so that the view model doesn’t need to return an OnClickListener. For starting other activities it also may be better to give the View a handler to deal with actions not related to the view model.