These are the mostly used terms while building an Android app. To optimize our networks calls and to prevent unnecessary creation of objects, one should apply these concepts during the development phase.
In this article we are going to see how to implement these by building a sample app.
So let’s get started!
First of all create a new project in Android Studio and let the gradle build finish!
Step 1: Update build.gradle
The very first step is to modify our build.gradle files by adding these stuffs. Add dagger plugins and some dependencies in your app level build.gradle file as shown below.
Also update your project level build.gradle also as shown below
Step 2: Add Internet permission to your manifest file.
Here along with the internet permission, we have also added android:usesCleartextTraffic=”true” because we are going to an endpoint which has http protocol instead of https protocol.
Step 3: Define package structure
We will make our classes according to this hierarchy. Now let’s move ahead!
Step 4: Create an Application class.
Now we will create an application class named BaseApplication
We will define here that we are going to use Hilt to implement dagger in our app by adding an annotation “@HintAndroidApp” over BaseApplication.
Step 5 : Define model classes
According to the incoming JSON object we have created out model classes
Step 6: Create a api package classes and interfaces
In this package we will create two interfaces namely, ApiService, ApiHelper and a class ApiHelperImpl. As the name suggests ApiService will service our network call and ApiHelper will help it to be accessed via repository maintaining encapsulation. ApiHelperImpl will be the class which will implement ApiHelper to provide functionality to ApiHelper functions. Also all the functions will be suspended, so that all network calls on background thread instead of main thread. Let’s see how!
In ApiHelperImpl we have injected ApiService in the constructor itself so we do not have to create new instance of ApiService instead it is passed as a dependency to the ApiHelperImpl. In this way we can have only one instance of ApiService throughout the application lifecycle for any number of network calls.
Step 7: Create a repository
Inside repository package we will create a MainRepository class which will call the function of ApiHelper to get the response.
Here also we made getEmployee() function suspended as ApiHelper function will also return a suspended function.
Step 8: Create AppModule object
Now it’s time to create a module object which will provide required instances as a dependency to other classes and maintain singleton behavior. We will now create an AppModule object as follows:
This object has an annotation “@Module” which tells it that it is a module object w.r.t dagger implementation.
Next it has “@InstallIn(ApplicationComponent::class)” annotation which tells it that this module will be available for complete application lifecycle not just for some activities or fragments. Like ApplicationComponent class we have ActivityComponent and FragmentComponent class as well for activities and fragments lifecycle scope.
Now inside this object we have define some functions like provideRetrofit(), provideOkHttpClient(), etc. which has annotations “@Singleton” and “@Provides” on them. These annotations tells it that only single instance of that particular class will be available throughout the application and will be passed whenever and wherever needed as a dependency.
Now rebuild your project to let Android studio generate some boilerplate code. After rebuilding you can see the generated code here:
You can check and analyze how it is working internally!
Step 9: Setup utility files
Now we will create some utility files to retrieve data inside other package.
These classes will be used to wrap our data to be used in a generic way into our UI.
Step 10: Implement UI
Now we have to implement our UI for that create a MainViewModel class inside ui package which should extend ViewModel class like this:
Here we have used “@ViewModelInject” instead of “@Inject” on constructor as hilt provides injection to viewmodels internally. So, we have passed mainRepository here in the constructor without creating another instance of it. As we can see here the function getEmployees() wraps the response inside the Resource class which we defined above.
Now we will create the adapter of the recyclerview to display employee information.
The layout for adapter will be:
The adapter class will be as follows:
This is a simple recyclerview adapter class. Here we have used DifferCallback to set data to adapter. It will add only new items to the list which are currently not present in the list.
It’s time to now create MainActivity.kt
The layout file will be as follows:
The MainActivity class will be as follows:
Here we have used an annotation “@AndroidEntryPoint”, this is used to tell the activity that we will be injecting dependency here. This is very important to make sure we add this otherwise DI will not work. Then we have attached an observer on response coming from viewmodel and handle data and progress according to the response.
So this was it! We have successfully implemented DI using Dagger-Hilt along with Retrofit using coroutines.
Now build and run your app!
For complete code reference checkout this GitHub repository. Happy coding!