Creating the Network Module with Hilt

Priyansh Kedia
CodeX
Published in
3 min readJul 9, 2021

--

In the previous blog, we read about the application module, and how we can inject the Application instance using Hilt. In this blog post, we will understand how to set up the network module using Hilt, followed by using MVVM architecture to make API calls using the network module.

Photo by Munro Studio on Unsplash

The Network Module 👑

We first start by creating a simple Kotlin class and name it NetworkModule.

We annotate this class using @Module and @InstallIn. You can read about these annotations here. We first start by creating a method that would help inject Gson. We will be using Gson for the serialization and deserialization of our JSON object.

@Provides
@Singleton
fun getGson(): Gson {
return GsonBuilder().serializeNulls().setLenient().create()
}

We annotate the above method using @Provides and @Singleton. These annotations were briefly explained in the previous blog.

serializeNulls() is used to specify that even null values will be serialized. By default, Gson omits the null fields.

setLenient() makes the Gson parser liberal in what it accepts. By default, it is strict and only accepts JSON.

But why did we create this method first?

This is because Gson is a dependency of one of the other methods that we will create in the NetworkModule.

Moving on, we will now create the method for the network interceptor.

The interceptor method

@Provides
@Singleton
fun getInterceptor(): Interceptor {
return Interceptor {
val request = it.request().newBuilder()
val actualRequest = request.build()
it.proceed(actualRequest)
}
}

The above method is used to inject the interceptor in the retrofit instance that we will be creating soon. You can also add a header to all your requests. This is how you can do this,

@Provides
@Singleton
fun getInterceptor(): Interceptor {
return Interceptor {
val request = it.request().newBuilder()
request.addHeader("Authorization", "<Your token here>")
val actualRequest = request.build()
it.proceed(actualRequest)
}
}

Next, we will create the method for OkHttpClient.

The OkHttpClient method

@Provides
@Singleton
fun getOkHttpClient(
interceptor: Interceptor
): OkHttpClient {
val httpBuilder = OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(50, TimeUnit.SECONDS)

return httpBuilder
.protocols(mutableListOf(Protocol.HTTP_1_1))
.build()
}

All these settings for the OkHttpClient specify the read, write, and connect timeouts. You can also add a network interceptor like Stetho. This can be done like this,

@Provides
@Singleton
fun getOkHttpClient(
interceptor: Interceptor
): OkHttpClient {
val httpBuilder = OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(StethoInterceptor())
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(50, TimeUnit.SECONDS)

return httpBuilder
.protocols(mutableListOf(Protocol.HTTP_1_1))
.build()
}

You can see that interceptor is a dependency of the getOkHttpClient method. Using Dagger injection, we do not need to create these dependencies individually.

We now create the method for Retrofit, which is used to establish network connections with the server.

The Retrofit Method

@Provides
@Singleton
fun getRetrofit(
client: OkHttpClient,
gson: Gson
): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build()
}

We add the converter factory to our retrofit, add the base URL, and the OkHttpClient. You can see that Gson and OkHttpClient are dependencies of this function.

Lastly, we will be creating a method that will help us connect the interface methods for our API endpoints.

The ApiClient Method

@Provides
@Singleton
fun getApiClient(retrofit: Retrofit): ApiClient {
return retrofit.create(ApiClient::class.java)
}

This method simply creates an instance of ApiClient, by connecting retrofit to it.

We will see how we create the ApiClient interface, and how we create the dependencies for ViewModels.

Jump to the next blog from here.

--

--