You know that early Android developers or potentially mediate Android developers might find is that they end up putting a bunch of code in their activity class and they know ends up with a very bloated activity class. So what this post suggests to you is how you might be able to divide out that code a little bit more intelligently.
What is Architecture component?
Architecture components are a growing set of libraries.They are meant for creating Android apps and the whole point of these libraries is to simplify things that might have been a little bit challenging with Android development.
Started with two libraries, a library for persistence on android and a library for lifecycle on Android and making lifecycle management easier.
The first is Room the second one is Lifecycle library and both of these libraries reached 1.0 stable in November so they are production ready and you could use them in your app safely. These libraries were built in a way where they can be used alone or they can work together just fine.So if you’re only looking for a solution to make SQLite database you could easily use Room alone without having to use other libraries if you want but they’re also designed in a way to really work well together.There is the third library called Paging library its purpose is to simplify lazily loading large data set for you.
Create an app in a way that it uses a reactive UI which means, in other words, the UI will automatically keep in sync with the database which is what are the powerful things you could do about that connection between Room and the Lifecycle library.
So what is the big principles of the guide is really encouraging you to have a separation of responsibilities for each of your classes.So i’m going to through each of the classes and talk about what their responsibility is.
The first class is the UI controller an activity or fragment.The responsibility of the UI controller is to display data. Basically, it’s telling views what to draw to the screen another responsibility that it has is capturing things like user interactions.Your activity is the one that knows if a user clicks a button.
But as soon as it gets that button click instead of processing itself it will pass on that information to a new class called the ViewModel. The ViewModel will also contain another new class called LiveData that the responsibility of the ViewModel class is to hold all of the UI data that is needed for your UI controller.
The ViewModel class then communicating with a class known as the Repository.Creating a Repository class is a convention and it’s a suggested best practice but it’s not part of the library. It’s not a new architecture component it’s just it’s a best practice and in simply put the Repository class contains the API through which you will get access to all of the apps data.
Room manages all of the local persistence of this the SQLite database.Room contains a bunch of different classes that work together including entities and DAO and database class and it’s built on top of SQLite.
Avoiding Strong References
Another core principle that I want to point out is we have separation responsibilities but we also have the idea that the classes only reference the class directly below them.what I mean is for your UI controller or your activity that class is only going to have a reference to the ViewModel. The ViewModel though will not have a reference back up to the activity and in addition the activity won’t reference the Repository or the database this sort of strict rule of avoiding strong references +like the activity to the database or in different parts of your architecture makes sure that you keep things modular and that your app doesn’t become a tangle of dependencies and what this means is that if at a later point you want to rewrite a portion of your app say that you want to replace the Room database with something else you can easily do that and you would only need to change references in the repository and not your entire app to be able to do that update it also makes thing more tastable.
In some cases, you’re going to want to be able to communicate information back from a sort of lower level on this diagram up for example, if some data changes at your database you’re gonna want to be able to communicate that back up to the UI. But the database doesn’t know about the activity. So how do we do that well you will be using the observer pattern and more specifically you will be using LiveData.In the past, you might have used callbacks but LiveData will replace that.
Room is SQLite object mapping library and it takes care of local data persistence for an app and Room has a lot of advantages over using the framework classes for example instead of using SQLite helper use Room you need to write a lot less boilerplate and one of the ways that it does this is that it maps database rows to objects and vice versa. So you don’t have to use intermediate values like cursors or content values you can get rid of all of those from your app. Room also does a handy thing where it validates your SQLite queries at compile time it actually won’t let you compile invalid SQL and it will also give a helpful error message so that if you wrote your SQL incorrectly you’ll know how to fix it finally Room has support to work well together with LiveData and Rxjava for that observability.
The Repository class functions as a clean API for handling all data operations.The Repository class functions as a mediator between different data source.You might be able to imagine an example where you’re getting both data from your network server and you’re also getting data from a local data cache the logic about whether to grab new data from the server or use the local cache data and when to do additional fetches all of that complexity would be inside of the Repository class and what this means is that when your UI code needs some data it doesn’t have to worry about all the complexity of life should Repository class get this from the network or should it get this with local data caches or whatever else you might have there. So it hides that complexity of where the data is actually coming from the rest of your app.
Lifecycle Library Classes
There is a couple of core classes and concepts that you’re not going to use directly that you should be generally aware of the.First of those in that in the lifecycle library, it has an object that represents a lifecycle.A Lifecycle in android and it’s just called the lifecycle.Similarly, lifecycle owner is an object that has a lifecycle, for example, an activity or fragment.Finally is the concept of lifecycle observation so you can actually make a lifecycle observer its interface for observing lifecycles so if you’ve ever had listeners or services that require you to write some like cleanup code and onStop those listeners and services could be using lifecycle observation to be doing that clean up for you.
ViewModels provide data for UI while a surviving configuration changes common example of a configuration change is rotated your device or changing languages as well. Because ViewModel survives configuration changes they can replace AsyncTask loaders more importantly though they encourage you to have this separation of responsibilities.
In the ViewModel class, we suggest that you have all of your UI data and then leave the activity class just to be responsible for actually drawing that UI data.
As you can see here my activity data is no longer in my activity I’ve moved it over to the ViewModel and my activity gets the data that it needs to be able to display itself by communicating with the ViewModel. The ViewModel survive rotation or configuration changes.If a configuration change happens is typical activity dies and it’s recreated but importantly that activity UI data did not go with it and all that my newly recreated activity has to do is reestablish a connection with the same ViewModel which continued living through.
ViewModel survive configuration changes but they don’t survive the activity being finished.So they’re not like a permanent thing that stays around forever they’re linked to an activity lifecycle but they’re not linked to like the app lifecycle or anything like that. So when the activity finishes such as if the user presses a back button of they go to their overview screen it actually swipes your activity off the screen the ViewModel also be destroyed as well so a ViewModel does not replace a database or persisting your data.An important thing to realize that ViewModel is not a replacement for
onSaveInstanceState even though they seemed similar.So if your device is very stressed out because there’s a lot of like memory constraints going on and your APIs in the background it’s possible that the os will just kill your app
onSaveInstanceState is actually useful for surviving this total app destruction ViewModels don’t survive this they they also get destroyed therefore in those cases you still need to use
onSaveInstanceState to get your UI data and your UI state back to what it was before.
LiveData is an object that is a data holder class and it’s also a lifecycle aware it also allows for data to be observed.
With the observer patterns you have an object called a subject and that subject will have a list of associated objects called observers that basically register with the subject and say hey I’m interested in you please tell me when you change so then when the subject’s state changes some of that causes it to change it knows about that list of observers so it’ll notify all of them and it will usually do by calling a method that is inside of that observer object.
So LiveData follows this pattern almost exactly so in our case the LiveData is the subject and you will be creating objects called observers which are the observers.
The other property of LiveData is it is lifecycle aware. LiveData actually uses lifecycle observation it observes a lifecycle to make sure that it only notifies observers when they are in a started or resumed state.
LiveData knows how to clean up observers when they’re no longer needed so if the activity that’s associated with the observer is destroyed the observer will clean itself up which means that you are never in a case where your LiveData is updating a destroyed activity and this makes it so they could not gonna have memory leaks.
- Reactive UI that update automatically when data changes
- Only updates UI in started/resumed state
- LiveData cleans up after itself automatically.
- Allows for the database to communicate to UI without knowing about it(Testability)