ViewModel is an Android architecture component responsible for managing UI-related data and logic. Its function definition is very similar to Persenter in MVP architecture, and it adds many convenient functions for development when used with other components.

The basic use

To define a ViewModel, we simply inherit the ViewModel abstract class:

public class MainViewModel extends ViewModel {
   
}
Copy the code

Then we can instantiate it in the activity/fragment:

MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
Copy the code

Note: If you want to use the full functionality of the ViewModel, you cannot create an instance of the ViewModel. Instead, you can create an instance of the ViewModelProvider class.

It is because of the way the ViewModel is created through the ViewModelProvider that the ViewModel has some more convenient and practical functions.

The life cycle

Because the ViewModel is created with an instance of the Activity/Fragment object (ViewModelProviders.of(this)) passed in, the ViewModel is aware of the lifecycle of the host.

The ViewModel is then self-destructed when the host onDestroy(). In addition, the Activity is treated as an Activity while the screen is rotated, with several lifecycle methods, but at this point the ViewModel is the same object as before and has not been recreated.

Shared data

public class MainViewModel extends ViewModel{ } public class Fragment1 extends Fragment{ @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class); } } public class Fragment2 extends Fragment{ @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class); }}Copy the code

In the example above, if Fragment1 and Fragment2 have the same host activity, they create the same ViewModel, and the data in the ViewModel can be shared.

Update the UI

The ViewModel can be used in conjunction with LiveData to update UI data without holding any references to the activity, which is one of the highlights and features of the overall component architecture.

public class MainViewModel extends ViewModel{
    MutableLiveData<String> data = new MutableLiveData<>();

    public LiveData<String> getData() {return data;
    }

    public void loadData(){// simulate a data request data.setValue("test");
    }

}

public class Fragment1 extends Fragment{
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainViewModel ViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        ViewModel.getData().observe(this,new Observer(){ @Override public void onChanged(String s){ textView.setText(s); }}); }}Copy the code

In the example above, the textView updates itself as the data source changes, whereas the ViewModel doesn’t need to worry about UI updates, just data changes.

Matters needing attention

The ViewModel may seem simple to use, but there are a few things you need to pay attention to in practice.

1. Initialize the data source

The ViewModel essentially manages the various LiveData sources, but it is important to initialize the data source before the external getData(), because the external will register the observer directly after obtaining the data source. If the data source is not initialized, the null pointer will be raised.

2. Data source update

In the above example, the loadData() method updates the data source directly with the current data object, but in practice it is possible that the data request module will return a new instance of LiveData each time the data is requested. In this case, the current data cannot be reassigned directly:

data = newData;
Copy the code

If you write that, the observer in the external setting will be invalidated.