CodeNewbie Community

loading...
Cover image for Room database. ViewModel

Room database. ViewModel

Tristan
・4 min read

Introduction

  • This series is going to be dedicated to the basics of Android Room library. I will be following the official google guide, HERE but I will be working in an order that makes more sense to me.

What is a ViewModel

  • The ViewModel class is designed to store and manage UI related data in a lifecycle contentious way. The ViewModel class allows data to survive configuration changes such as screen rotations. Basically its a class that eases the use of data in our UI components like fragments and activities

Problems faced by the UI

  • The Android framework manages the life cycles of UI controllers, like activities and fragments. The framework may decide to destroy or recreate a UI controller in response to certain user actions or device events that are completely out of our control.

  • When the Android system destroys and recreates a UI component for any reason it creates 2 main problems

1) Restoring the UI data : if a system destroys or recreate a UI controller any transient UI related data you store in them is lost. When an activity is recreated for a configuration change, the new activity has to re-fetch the data. To solve this problem we could use the onSaveInstanceState() method and restore its data from the bundle in onCreate(). However, this approach is only meant for small amounts of data, not large amounts like we will be using.

2) Asynchronous calls : the UI controller needs to be able to manage asynchronous calls and ensure that the system cleans them up after its destroyed the UI controller to avoid avoid potential memory leaks. This management requires a lot of maintenance and is ultimately a waste of resources since the object will have to reissue calls it has already made.

Why use ViewModel?

  • Now UI controllers are primarily intended to display UI data, react to user actions, or handle operating system communication, like permission requests. Making UI controllers also handle loading data form a database or network calls adds unwanted clutter to the class. This is also a violation of the separation of concerns principle that we try to abide by in programming. It also just makes the class harder to test.

  • A much better and more efficient approach is to separate out the view data from the UI controller logic. We can do this by creating a ViewModel

Creating a ViewModel

  • We will be using a ViewModel class that is responsible for preparing and managing the data for our activities or fragments.
  • ViewModel objects are automatically retained during configuration changes so data they hold is immediately available to the next activity or fragment instance. This means we can have large amounts of data and only make one asynchronous call. Solving our two problems from earlier. With all that being said lets look at the code.
public class WordViewModel extends AndroidViewModel {
    private WordRepository mRepository;
    private final LiveData<List<Word>> mAllWords;

    public WordViewModel( Application application) {
        super(application);
        mRepository = new WordRepository(application);
        mAllWords = mRepository.getAllWords();
    }

    LiveData<List<Word>> getAllWords(){
        return mAllWords;
    }

    public void insert(Word word){
        mRepository.insert(word);
    }

}
Enter fullscreen mode Exit fullscreen mode

public class WordViewModel extends AndroidViewModel

  • The first thing that you probably noticed is that instead of extending ViewModel we extend AndroidViewModel. AndroidViewModel is a subclass of ViewModel so it does all of the same things that ViewModel does. The only difference is that AndroidViewModel is meant to be used when we are using global application context like we are. So just know that we are using AndroidViewModel over ViewModel because our program uses application context.

private WordRepository mRepository;

  • This is just a private member variable of type WordRepository. Remember a repository is an abstraction layer that we created for interacting with the database.

private final LiveData< List< Word > > mAllWords

  • Just another private final member variable but it is of type LiveData which will ultimately be used to store an updateable list of data.

public WordViewModel( Application application){...}

  • This is our constructor and we pass it a argument of type Application which is the global state of our application. We need to pass it this variable because AndroidViewModel needs it to operate properly. By calling super(application) we are calling the public constructor of AndroidViewModel. Our WordRepository also needs this application context.

mRepository = new WordRepository(application);

  • The next thing we do inside of our constructor is assign the member variable mRepository an actual instance of our WordRepository. This is important because if we don't do this we can not interact with our database. Also, notice that we are passing it application this will get used by our database when instantiating.

mAllWords = mRepository.getAllWords();

  • Here we are assigning a LiveData set of words to our mAllWords member variable.

LiveData< List < Word > > getAllWords(){...}

  • Just a basic getter method of our data of type LiveData. This method will eventually be used to hook up our data to our UI.

public void insert(Word word){...}

  • This is used to insert a Word entity into our database. Notice that we are interacting with the database through our repository.

  • With that we have successfully created a basic ViewModel.

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.

Discussion (0)