Need help with android-mvvm?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

445 Stars 84 Forks Apache License 2.0 175 Commits 17 Opened issues


MVVM on Android using RxJava and Data Binding

Services available


Need anything else?

Contributors list

# 134,786
React N...
150 commits
# 504,668
2 commits
# 206,762
1 commit

Android MVVM

Build Status Download


  1. Sample project to demonstrate a coding pattern based on MVVM with focus on
    1. Easy composition of views
    2. Minimising boilerplate of setting up views
    3. Reuse of presentation logic
  2. A library with essential tools for the pattern


  1. Android Data Binding
  2. RxJava
  3. Introduction to this pattern @DroidconIN

Quick Tutorial

Getting Started provides a tutorial to setup the library and gives an idea about its functionality. As the main deliverable of this library is the pattern, it is important to understand the principles behind it, so that the pattern can be applied even at places where the library APIs aren't available.

MVVM Implementation

This pattern makes use of Data Binding, such that views contain exactly 1 variable

i.e. ViewModel. Idea is that the ViewModel should have all information required to display the View. Multiple views can share a single view model. This helps in reusing functionality for a different layout.

Using a single variable

provides a consistent mechanism to configure any View:
viewBinding.setVariable(BR.vm, viewModel)

Note that this mechanism needs to be configured by providing an instance of

interface. This interface describes how a ViewModel is bound to a View. The variable name to be used in xmls (
in this example) should be specified here.
BindingUtils.setDefaultBinder(new ViewModelBinder() {
    public void bind(ViewDataBinding viewDataBinding, ViewModel viewModel) {
        viewDataBinding.setVariable(BR.vm, viewModel);

This code can be placed in your

method of Application/Activity.

Creating a View Model

A view model is a POJO formed by fields for storing data (for input/output) and event listeners. In MVVM, interaction between ViewModel and View happens via changes in data OR method calls. These interactions can be categorized based on direction & type of data flow:

  1. Output Data (ViewModel -> View) ViewModel changes its data, View listens for changes & updates itself Example: ViewModel is running a timer, and updating its

    variable. View is listening for changes and updating itself whenever it gets a callback.
  2. Input Data (View -> ViewModel) View requests ViewModel to update its data (such as capturing text input) Example: Form containing various inputs like

  3. Input Events (View -> ViewModel) View invokes functions on ViewModel when certain events occur (such as onSwipe/onClick/onFocused) Note the difference between

    . Any input can be represented as an
    . However, wherever there is persistence in input, representing them as
    is convenient. For example, if a user has typed
    in EditText, this input is represented as a String variable with value
    . When user types
    , the text changed "event" causes the data to change to
    . Working with data is better in this example. Consider an example of a Button click. There is no data change that's implicitly happening on click. Hence, this input is represented as an

Now, we'll see how these three interactions are implemented in this pattern.

Output Data

This is stored as a field in the ViewModel class. If the value is constant, it can be simply declared as a

final TYPE
. If its changing, it is declared as an
, provided by data binding. Example for displaying text (String)
public class OutputDataViewModel {
  public final String constantOutput = "";
  public final ObservableField changingOutput = new ObservableField("");

Note that everything is

. To modify the
, its
function is used. Example:
this.changingOutput.set("new value");
. Data binding takes care of adding listeners and updating the view.

In XML, this data is displayed by referring to these fields.

<textview ... android:text="@{vm.changingOutput}">

Input Data

As input data implies that it cannot be constant, it is always stored as an

public class InputDataViewModel {
  public final ObservableField inputText = new ObservableField("");

Because we want the view to update the value of this

, Two Way Binding is used.


enables two way binding

Input Events

EventListeners can be implemented simply as methods in ViewModel ```java public class EventViewModel { MessageHelper messageHelper; // This is an external dependency

public void onClick() {"Something got clicked"); }

Observable and Data Binding's 
types. This allows the use of RxJava's operators to manipulate the data.

Rx -> DataBinding


has a
method that returns an
. Amount needs to be formatted before displaying. This can be implemented as follows:
public final ReadOnlyField totalAmountText;
public CartViewModel(Cart cart) {
  totalAmountText = FieldUtils.toField(cart.getTotalAmount().map(a -> a + " Rs"));


method returns an instance of
which extends
. Note that
method in
does nothing. See Observables And Setters for the rationale behind this.

DataBinding -> Rx

Example: Error needs to be shown if input text is empty.

static import FieldUtils.toObservable;
static import FieldUtils.toField;

public final ObservableField inputText = new ObservableField<>(""); public final ReadOnlyField errorVisible = toField(toObservable(inputText).map(text -> text.isEmpty()));

A binding adapter would be required to use boolean for

public static void bindVisibility(@NonNull View view, @Nullable Boolean visible) {
    int visibility = (visible != null && visible) ? View.VISIBLE : View.GONE;

See and the corresponding activity_search.xml for another example in which the search results get updated as user updates the query.

RxJava versions

Both RxJava 1.x and 2.x are supported. For RxJava 1.x support, an additional dependency needs to be added: ``` compile ''

// Under android config android { packagingOptions { exclude 'META-INF/' } } ```

Note that rxjava-compat internally depends on both RxJava2 and RxJava

This adds equivalent BindingAdapters for

. This also includes
class for conversions between
. Thus, the syntax is same except for the imports.

See for an example implemented using


Code-less View Setup

Views are setup using XML ONLY. This is the core idea behind this pattern.

s are used to create a declarative API with essential arguments.

Thus, whenever it is required to write code for setting up a view, create a

instead and use XML attributes.

This also applies to complex views such as

which need setting up adapters. These views are containers which display (multiple) child views. This particular operation of nesting views is termed as
View Composition
. As the choice of pattern (MVVM/MVP) greatly affects how
View Composition
is done, this library provides tools to deal with this aspect. However, there are other scenarios where code is required to setup views. Such code gets moved to a
and the view is setup using XML attributes.

The BindingUtils file contains

s provided by this library. These are good examples to learn about this approach.

If this is not doable in some case, it implies that you need a functionality that's not provided by existing views. Create a custom View in that case.

View Composition

Just like code, UI also needs to be reused at multiple pages. Just like classes are split into smaller classes, views are split into smaller views to make them reusable.

Lets say a page requires to combine 3 functionalities. There can be 1 ViewModel to represent each functionality. Similar to how layout hierarchy is created using

, a parent ViewModel is created that contains child ViewModels as fields. Data Binding allows binding included layout's variables.

Thus, with a simple

, this layout gets added on the page. The only Java code required is to add the 
field in the outer ViewModel.

Composing a dynamic list of functionalities

It is very common to display a dynamic number of views in a RecyclerView or a ViewPager. The type of each child view could also vary based on some data. Writing a new adapter to support different view types results in duplicate code.

With MVVM, as we have a consistent mechanism to setup any view, it is now possible to write abstract adapters, which can be used for displaying any type of views. This reduces a lot of boilerplate. For example, a RecyclerView can be setup with these two inputs: -

: A list of ViewModels. The adapter notifies itself when the list updates -
: An interface which decides which View should be used for a ViewModel

Using Data Binding, we can create attributes so that these inputs can be provided in XML:

This creates a nice declarative API to setup views like RecyclerView/ViewPager.

Using different views

Static methods are defined which return custom instances of

public class ViewProviders {
  public static ViewProvider getItemListing() {
    return new ViewProvider() {
              public int getView(ViewModel vm) {
                if (vm instanceof ItemViewModel) {
                  return ((ItemViewModel) vm).hasImage() ? R.layout.row_item_with_image : R.layout.row_item_without_image;
                } else if (vm instanceof SomeOtherViewModel) {
                  return R.layout.some_other_view;
                return 0;

This method is referenced in XML when setting up the view. ```xml


Supported Attributes

Following attributes are provided with this library.

@BindingAdapter({"items", "view_provider"})
public static void bindAdapterWithDefaultBinder(RecyclerView recyclerView, Observable> items, ViewProvider viewProvider);

@BindingAdapter({"items", "view_provider"}) public static void bindAdapterWithDefaultBinder(ViewPager viewPager, Observable> items, ViewProvider viewProvider);

@BindingConversion public static ViewProvider getViewProviderForStaticLayout(@LayoutRes final int layoutId);

@BindingConversion public static Observable> toListObservable List specificList);

@BindingAdapter("layout_vertical") public static void bindLayoutManager(RecyclerView recyclerView, boolean vertical);

Check the source ( to know how these work.

What if I need to use some other View?

Every application has different requirements. It may not be feasible to create a generic API that works well for all usecases. This project aims to provide a pattern so you can build your own custom XML attributes that fulfill your usecase. You can use as a reference to roll out your own attributes.

What if I want to customize these adapters?

Although BindingAdapters can be overridden, it hasn't been specified how databinding resolves the conflicts. Based on experiments, adapters in client project are preferred over adapters from library. However, having identical adapters in a same module will result in undeterministic results.

The sample project overrides these BindingAdapters to check memory leaks.

Composition Strategy

Here are some scenarios, and the way in which this pattern resolves them:

Multiple layouts for displaying same information

A common view model that can bind to all views.

Two layouts, which share some common functionality

There are many ways depending on the situation. - Extract common functionality into one child ViewModel. Both view models keep a reference of child ViewModel - Two view models, one extending the other - Two view models which extend from a common base - Single view model with all functionality - This approach is possible only because ViewModel has no dependency to a view. In architectures like MVP, this is difficult, as the Presenter has a dependency on a View

Functional ViewModels

RxJava provides several operators to compose Observables. Conversion between

fields, enables the use of all these operators in ViewModels, which eliminates the need for mutable state (in most cases).

Consider an example of showing ProgressBar while api is loading. Traditional example: ```java void load() { displayProgress(); service.loadData(new Callback() { @Override void onSuccess(String data) { displayData(data); }

void onError() {

}); } ```

By keeping loadedData as an

, we can derive progressVisibility by making use of the Using operator. From
can be derived. Thus, there are no mutable states, only mapping from one Observable to other. Also, note that there is no need for subscriptions inside ViewModel as View will subscribe to the data after binding.

See for this example.


ViewModels are unaware about lifecycle of View. This means that ViewModel code comes into action only when View invokes it. ViewModel simply defines the logic of transforming inputs to outputs. This is similar to

pure functions
from functional programming, which provide output based on its inputs only.

There are scenarios where ViewModel needs to know about lifecycle of the View. This feature is in the roadmap. Do contribute!

More Information

Wiki contains links to more content around this topic.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.