Beginners' Guide to working with APIs using MVVM, Coroutines and LiveData.
As an Android app becomes complex, so are the tools used. Most apps actually connect to an online service hence working with APIs plays a critical role in developing apps. It can be a rough place for beginner android developers to wrap their head around some concepts.
The purpose of this tutorial is to help an android developer better understand how to work with APIs while still using the MVVM architecture, Coroutines and LiveData.
Let's have a look at some of the features that we will be using.
- Stands for Model-View-ViewModel
- It is a software architecture that separates the development of the UI (the view) from the business and presentation logic (the model).
- Planning the architecture to use is important as it allows a developer to create complex, robust, good quality, easy to maintain applications even as the size of the codebase increases.
-The Model – Domain model. Has the actual data or information. We will use data-models that compose outputs from a API, by ensuring the latest data is retrieved. They are usually structs or simple classes.
-The View – This is the structure, the layout and the appearance. It is what the user sees on the screen, the UI. It is a representation of the data in the model and receives user interactions such as clicks.
-The ViewModel – Transforms the model information into values that can be passed on a view. They are usually classes,so they can be passed around as references.
- It is a type-safe REST client for android developed by square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests.
- Is an observable data holder class. It respects the Lifecycle of other app components such as activities, fragments, services. This way, LiveData only updates app components that are in an activitys’ Lifecycle state. In simple terms, since were using MVVM architecture, the ViewModel is not aware of the activity Lifecycle and it has to be told, that is why it is known as LiveData, data aware of the Lifecycle of the interested observer.
- Concurrency design pattern that simplifies code that executes asynchronously
- They help manage long running tasks that might block the main thread and cause an app to become unresponsive.
- Since we are working with an API, network requests must be made. This kind of tasks are long running and may take long for an app to wait for them. The main thread handles UI and user interactions. If there is too much work happening on it, the app appears to “hang”, or slow down. This kind of task should be done without locking the main thread
Let's get right into the code
We shall be consuming https://akabab.github.io/superhero-api/api/ to fetch data. No API key is required for this.
We shall have three main packages, data,ui and utils.
This is where we perform data operations.
Step 1 - Adding Dependencies
For this tutorial, we shall be using RecyclerViews, CardView and GridLayout to display the superhero characters.
Step 2 - Allow internet permission
Since the data is only accessible through the internet, you will require permission to use the app's internet. Add the following just above the application tag in the manifest file.
Step 3 - Create a Model class
The model class will handle the response from the API. One way to generate a model class is by installing a JSON to Kotlin Class plugin that converts Json strings to Kotlin data classes. File->Settings->Plugins and search for the JSON TO KOTLIN CLASS plugin then install it and restart your IDE.
Install the plugin. To generate the data classes,use this URL to access the raw data in Json format
We shall use the model package we created. right click on the package(model)
Copy the raw data on to the provided field and name your class, Hero. Here is a snippet of one of the classes.
@SerializedName is used if you wish to change the variable name of a data class.
You might have noticed close to seven classes, we won't necessarily use all of them, but as an app becomes more complex, the possibility of using all are high.
Step 4 - Create an API interface using retrofit2
We will use the GET request to pass data. Suspend functions are called from Coroutines. The suspend keyword helps the coroutine pause, perform the required job on a network thread (if Dispatchers.IO) is used, wait for the response, and then resumes from where it left off once the response is available. This will be seen on the MainViewModel.
Step 5- Create an API helper
Step 6 - Create a Retrofit Builder
This creates the singleton object of Retrofit class. getRetrofit() function, this means that whenever we need to call this getRetrofit() method, we’ll not have to create the object. companion object is same as Java’s static method. The BASE_URL,contains the url of the webservice.
Step 7 - Create a Repository
The repository interacts with the API using retrofit.
It will be utilized by the ViewModel
Contains helper classes and functions
Step 1 - Create Status class
The enum class represents the UI state
Step 2 - Create Resource class
This class is responsible for communication of the current state of the Network call to the UI layer
They help us encapsulate our repository responses according to their state, making it easy for views to display information as will be seen in the MainActivity.
This is where your activities and fragments go. It also contains ViewModel. All these are helping to display data to the user.
Step 1 - The main activity layout.
We have a RecyclerView and Progressbar
This represents an individual item in the RecyclerView in a CardView
Step 2 - Create an adapter package in the UI package
The adapter sets the items in the recyclerview. Our adapter has an image and one textview to display the data.
- We have used Glide library to retrieve superhero images from the URL. You can try out other libraries such as Picasso and Coil
Step 3 - Create the view package
This contains the MainActivity.
- Set up the ViewModels
- Set up the UI
- Set up observers
Step 4 - Create the ViewModel package
The ViewModel is used by the view to interact with the API via the repository. The View will also use the ViewModel to observe changes in the list, thus ensuring a seamless retrieval of data to display in the UI. Basically a ViewModel class is responsible for managing the data
- Main ViewModel
- ViewModel factory
Build your project and run it. You should be able to see the data on the UI.
Common errors to check out for
- Make sure you add the internet permission in the manifest file.
You can build on the project by adding other frameworks and features.
- You can include a details fragment to show details of a superhero.
- Adding a database to store data and to display data in case a user is out of connection.
- Add dependency Injection
- Writing tests(Unit and UI)
Use your creativity, the possibilities are endless.
Well, that is pretty much it. Happy Coding!!