As discussed in last part here , we will start with our little project. It is efficient to separate out view data ownership from UI controller logic. View model is responsible for preparing data for UI. Our basic requirement is the app which will fetch me a new Quote from mentioned category every time I open it. But while fetching, we should not be kept waiting and instead be presented with the last quote which we fetched. Slow internet can potentially become long lasting quote fetching operation and irritating for user if shown empty UI. Plus we need a mechanism by which we can refresh the quote from app by pushing the content down. While doing all this, we need to make sure that our code is maintainable, have proper architecture and testable!
I am assuming at this time that you know the basics of Android Development like how to create new Android Project in android studio and the file structure of the same. If you don’t, I would suggest you visit this link and familiarize yourself with Android project structure and gradle builds.
Create new Android Project by following this guide. You can choose any activity you like, I am choosing bottom navigation activity. We will create package structure as shown below for keeping our code organized.
I have divided code into different packages as explained below,
- Activity : This package will contain all the activities and fragments source files.
- Constants : This package will contain all the constants we will use throughout our code base.
- View Model : This package will contain our view model. Business logic will come under this package.
- OnlineData : This package will contain source files related to data fetching from REST API.
- PersistentData : This package will contain source related to offline cached data.
- POJO: Plain Old Java Objects
Later on, we will add more packages as code base grows like adapters, network etc.
Now you can argue that this is not the right package classification but hey, programming is creative field and you are always welcome to try out new things and suggest me as well!
Below are our starting implementations. Please note even though I have given code fragments here, I would recommend not to copy those from here but instead from github (by forking the project). Reason being, there might be syntax error in these codes and code is written with proper comments on git. Plus you would be able to contribute there as well.
We need Quote and Author for our UI. This is simple POJO class Quote which holds our quote data. Getters and Setters for author and category are omitted for brevity. But you need to include them while writing this code.
We will create a
QuoteViewModel based on the View Model class to keep this information.
A ViewModel provides the data for a specific UI component, such as a fragment or activity, and handles the communication with the business part of data handling, such as calling other components to load the data or forwarding user modifications. The View Model does not know about the View and is not affected by configuration changes such as recreating an activity due to rotation.
We have wrapped our Quote in LiveData.
LiveData is an observable data holder. It lets the components in your app observe
LiveDataobjects for changes without creating explicit and rigid dependency paths between them. LiveData also respects the lifecycle state of your app components (activities, fragments, services) and does the right thing to prevent object leaking so that your app does not consume more memory. So no more Out of Memory Error (duh!)
So whenever quote data is changed, fragment will be notified to update it UI. (only if fragment is active, because we are using Lifecycle aware component i.e. LiveData)
In our fragment, we will override two methods onCreateView and onActivityCreated.
We are inflating fragment view from fragment_quote.xml.
We are obtaining instance of our QuoteViewModel from ViewModelProviders class. We are sending context of fragment as argument to ViewModelProvider, so even if activity is destroyed and recreated (while auto-rotation), we will get the same QuoteViewModel object. You can learn more about scope of View Model object here.
As you can see from above figure, ViewModel objects are scoped to the
Lifecycle passed to the
ViewModelProvider (fragment in our case) when getting the View Model. The View Model stays in memory until the
Lifecycle scope goes away permanently—in the case of an activity, when it finishes; in the case of a fragment, when it’s detached.
I have delegated work of getting actual quote (either from Internet or SQLite) from QuoteRepository.java
Even though it may seem little overkill to have different class for such a small task but it helps keeping the separation of concern principle strong. And plus it will help once our code base grows. We will discuss more about API we are using to fetch the quote and use of Retrofit library along with QuoteRepository class in next article.
I will be writing more articles about tips and tricks for making most of your android application in future, subscribe The Tech Guru newsletter for getting the articles directly in your inbox. Subscription box can be found on top right side of this article of you are on PC and at the bottom of this article if you are on mobile device.