App Development

Google I/O 2017: the ViewModel is nice from up here

sunset view from above clouds

Configuration changes in Android are integral to how the operating system works. They allow us to tear down and rebuild Activities on orientation changes for one. Maintaining a consistent UI state across orientation changes can be a little tricky though, and we often lose results from network calls. You can use onSaveInstanceState, but it’s really only meant for small data, such as UI state. Passing in large sets of data to saved state isn’t really how it’s meant to be used. At Google I/O, Google announced a new library called Lifecycle that includes a variety of Lifecycle-aware components. One of these components solves this very problem: ViewModels.

You may have heard the term ViewModel before. It’s core to architectural approaches such as MVVM (it’s the VM), and is the new suggested approach to architecture that Google has put forth. The ViewModels included in the Lifecycle allow you to have data that lives through configuration changes to prevent having to redo work. An extra bonus: When doing work such as asynchronous network calls, using these ViewModels prevents you from needing to either redo these network calls or rig together something like a headless Fragment to keep the state of the network call. It all just lives seamlessly between orientation changes.

First off, let’s add the Lifecycle dependencies:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }
    }
}


dependencies {
   ...
   compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
   annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"
   ...
}

We’ll continue from our Lifecycle and LiveData post and continue to improve our simple Barometer application by migrating it to use a ViewModel to pull as much as possible out of our Activity components. We can start by creating our BarometerViewModel which extends the Lifecycle’s ViewModel class. We’ll move the BarometerLiveData into this ViewModel, so everything regarding the logic you’d need to add when new sensor data arrives is completely out of the Activity.

public class BarometerViewModel extends AndroidViewModel { // AndroidViewModel just offers you an easy getApplication(). 
    private BarometerLiveData data;

    public BarometerViewModel(Application app) {
        super(app);
        data = new BarometerLiveData(getApplication()); 
    }

    public void startObserving(LifecycleOwner lifecycleOwner) {
        data.observe(lifecycleOwner, sensorData -> {
            // do things
        });
    }
}

After we’ve setup our ViewModel (which in this case is using an AndroidViewModel so we can have an easy way to get the Application Context), we can then use that ViewModel in our Activity. The ViewModelProviders class fetches either a new ViewModel if none exist, or the existing ViewModel if one does exist, and works with both Fragments and Activities.

public class BarometerActivity extends LifecycleActivity {
    private BarometerViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = ViewModelProviders.of(this).get(BarometerViewModel.class);
        viewModel.startObserving(this);
    }
}

As you can see, this leaves a very empty, very happy Activity that only needs to worry about fulfilling its main duty of being a contract between your app and the Android OS. You would still need to manipulate views within the Activity, but that would be easy to get around using Databinding! I won’t get super in depth about using Databinding, but for a simple example, see below:

https://gist.github.com/Richie97/2be3d6f0cc2565d66929e0ad4f96be21

IMPORTANT NOTE: ViewModels are super cool, and they survive orientation changes and other light configuration changes. They DO NOT survive process death, so they do not save you from saving important state that needs to live through Android OS triggered Activity destruction. For that, you should definitely check out Room, which is Google’s new Sqlite library which is also a part of their new architecture libs, to save data long term.

Quickstart-Guide-to-Kotlin-Multiplatform

A Quick Start Guide to Kotlin Multiplatform

Kotlin Multiplatform, though still experimental, is a great up-and-coming solution...

Read the article