0% found this document useful (0 votes)
50 views

Android Architecture

Android Architecture: Hilt, MVVM, Kotlin Coroutines, Live Data, Room and Retrofit (ft. Rick and Morty)

Uploaded by

Alek
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views

Android Architecture

Android Architecture: Hilt, MVVM, Kotlin Coroutines, Live Data, Room and Retrofit (ft. Rick and Morty)

Uploaded by

Alek
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 11

Android Architecture: Hilt,

MVVM, Kotlin Coroutines, Live


Data, Room and Retrofit (ft.
Rick and Morty)

Santiago Beroch
·

When developing an Android app it is important to plan the


architecture of the project. This will allow us to create complex, robust,
good quality, easy to maintain applications.

Today I want to show you my approach to using the recommended


practices in Android development.

As you know, writing all of our app code in an Activity or Fragment is a


common mistake. We should separate the different concerns of our
app components. This next diagram will show you the modules and
their interactions that we will be using:
Android Architecture Components

The project
We will be using the Rick and Morty API, from where we will extract
character information to show them in a RecyclerView, and by clicking
one of its items the app will display the detail of one character. Simple.
The app

And this is the project’s folder structure:


Folder Structure

That could seem like a lot. Here is some explanation:

data: Our M (Model) in MVVM. Where we perform data operations.

di: Dependency Injection with the help of Hilt.

ui: Our Fragments and ViewModels helping to display data to the user.

utils: Helper classes and functions.


I recommend that you have a look at the GitHub repository while you
follow this tutorial.
sberoch/RickAndMorty-AndroidArchitectureSample
A Rick And Morty simple app to show one approach to using some of the best practices
in Android Development. …
github.com

One last thing before continuing. The API returns this response when
asking for a list of characters

We are getting a paginated response. The actual characters are


returned under “results”. That’s why you will find three classes under
the folder entities. But the most important one is Character.

Having said that, we move on to Hilt and DI.

Hilt
This is not a DI tutorial so I strongly advise to get a little more familiar
with the concept before continuing. I’ll briefly explain it anyway.

It is very common for applications where concerns are separated that


some of the components have dependencies.
The ViewModel depends on the Repository to get the data. But the
Repository depends on a CharacterRemoteDataSource and
a CharacterDao as well. And this is a simple app. It could turn into a
dependency hell pretty fast.
Hilt comes to the rescue. We just need to inform where do we need to
inject those dependencies and where should it get them from.

We start by creating in the root folder a class that inherits from


Application, to annotate it, informing that we will use Hilt in the app.
MainApplication.kt

Then, we need to annotate each Activity and Fragment as


AndroidEntryPoints:
MainActivity.kt
CharacterDetailFragment.kt

Our next step is to now create our Module inside the di folder. If you
are not so familiar with di concepts, think of the module as the “bag”
from where we will get our dependencies from. (I’ll show many
dependencies from upcoming sections of this tutorial, so don’t be
scared if you don’t understand all of them now).
AppModule.kt

@Module annotates the object to indicate that we will get our


dependencies from here. We’ll only use one in this simple app, but
larger scale projects usually have many modules.

@Singleton will force that only one instance of the dependency will be


created and used across the entire app.

@Provides indicates that the upcoming function will provide a


dependency.
So how do I do the injection?
@Inject

ViewModel, LiveData, and data display.


Thanks to the usage of LiveData and Kotlin Coroutines we can avoid
callbacks and have a really simple way to present our data to our views.
This is how this ViewModel does it:
CharactersViewModel.kt

You may be wondering about Resource. It is this helper class


Resource.kt

It helps us encapsulate our repository responses according to their


state, making it easy for our views to display information accordingly.
This is how CharactersFragment observes a LiveData value and
updates itself accordingly.
CharactersFragment.kt (characters observer)

We have our presentation layer. How do I get my data?

Retrofit and remote data.


Retrofit helps us access remote data from our app. You can see how to
build a Retrofit object in AppModule.kt. We also need to code
interfaces with the HTTP operations that we will perform to
communicate with the API.
CharacterService.kt
The suspend modifier is brought to us by Kotlin Coroutines, it
indicates that the following function will execute in a coroutine (similar
to a thread) allowing us to keep the UI thread unblocked while long
lasting operations such as getting our data from the internet are being
executed.

This CharacterService is used by CharacterRemoteDataSource


CharacterRemoteDataSource.kt

Why do we do this? Fair question. getResult encapsulates the Retrofit


response in a Resource, so that we can catch errors nicely.
BaseDataSource.kt

Room and local data storage


On the other hand, we are also interested in storing and getting data
from a local database. We need it in order to show at least something to
our users when they are out of connection. If you are familiar with the
concept, we are going to use it as a cache for our system.

Room brings us a nice interface to work with local databases. Here’s we


build one:
AppDatabase.kt

Don’t forget to include all the entities you want to persist in


the @Database annotation. In order for Room to see our entities, we
will need to also annotate them.
Character.kt
Lastly, we need to specify the operation that we will be performing on
the database. That’s where our DAOs kick in (Data Access Object)
CharacterDao.kt

Note that Room has LiveData support, so you can get observable values
from the database. And Kotlin Coroutines makes it even easier by
letting us suspend our Room functions.

Repository and our caching strategy


Let’s join both of our data sources. This is the time where we need to
plan a data access strategy. Think, for example, in the process of
getting a Character.

 First we need to let our LiveData know that we are looking for
the Character, so that it should have a LOADING state.

 Then, we would like to get that character from the local data
source, because it is faster than getting it from the internet. If it
finds it, we are changing the state to a SUCCESS

 Regardless of the result of the local database operation, we


would want to keep our app synced, so we are fetching that
character from the internet as well (but remember that the ui
thread won’t be blocked and the user could already be shown
the correct character information because of it being in the
database!).
 Finally, we need to save our result from the remote call in the
database, in order to keep it updated.

We will be doing all of this in our Repository:


CharacterRepository.kt

The performGetOperation is defined following the strategy we discussed:


DataAccessStrategy.kt

I want to highlight the first line where we do liveData(Dispatchers.IO)

Thanks to Kotlin Coroutines and LiveData, when we do that we are


launching a new IO coroutine, therefore letting us use our suspend
funcions, and we are as well storing our results in a LiveData holder,
which is being observed by the ViewModel.

And that’s it!

Further Steps
We made it to the end. I hope I was clear throughout the tutorial.

We have some TODOs that I omitted in order to keep things short:

 We are syncing all the time with the strategy I presented, and
your application might not need it. Keep your needs in mind
and develop a smart strategy.
 Also, we are only performing get operations. What if we need to
upload something to a server? The strategy will also be
different in such case.

 The API paginates its characters. Why don’t we? Take a look at
Paging Library by Jetpack.

 Testing is yet to be made.

That’s all. Remember you can find all the code I used in the GitHub
repository
sberoch/RickAndMorty-AndroidArchitectureSample
A Rick And Morty simple app to show one approach to using some of the best practices
in Android Development. …
github.com

And if any of this was useful to you, leave a Clap! I would be very
grateful and motivated for a next tutorial.

Source : https://itnext.io/android-architecture-hilt-mvvm-kotlin-coroutines-live-data-room-and-retrofit-
ft-8b746cab4a06

You might also like