Sling Academy
Home/Kotlin/Kotlin - Adding Headers and Interceptors in Retrofit

Kotlin - Adding Headers and Interceptors in Retrofit

Last updated: December 05, 2024

Retrofit is a type-safe HTTP client for Android and Java, used for making API calls easier and much more manageable. In this article, we’ll delve into how to add headers and interceptors when making calls with Retrofit in Kotlin.

Introduction to Retrofit

Retrofit simplifies HTTP communication by transforming your HTTP API into a Java interface, adding convenience with the use of annotations for converting JSON responses into Java/Kotlin objects.

Setting Up Retrofit

To use Retrofit in a Kotlin project, first, you need to add the necessary dependencies. Typically, this will include Retrofit itself, a JSON parser like Gson, and logging utilities:

dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
}

Adding Headers in Retrofit

In many use cases, APIs will require you to send headers for authentication or content-type definitions. You can statically add headers by annotating your API interface methods with @Headers:

interface ApiService {
    @Headers("Accept: application/json")
    @GET("/users")
    suspend fun getUsers(): List<User>
}

For dynamic headers, you should use the @Header annotation in the method signature. This approach is suitable when you want to pass headers at runtime:

interface ApiService {
    @GET("/users")
    suspend fun getUsers(@Header("Authorization") token: String): List<User>
}

Interceptors in Retrofit

Interceptors are a great way to manipulate requests and responses. They're widely used for adding request-level customization like logging, modifying headers, and error handling. There's a built-in way in OkHttp, a network library that underpins Retrofit, to declare interceptors.

Example of Adding an Interceptor

val interceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY
}

val client = OkHttpClient.Builder()
    .addInterceptor(interceptor)
    .build()

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.example.com")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

In the example above, the HttpLoggingInterceptor is used to log the body of HTTP communication. This is especially helpful during development for tracking request parameters and server responses.

Adding a Custom Interceptor

Creating a custom interceptor can be done by implementing the Interceptor interface. Here is an example on how to add a token to every request:

class AuthInterceptor(private val authToken: String) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request().newBuilder()
            .addHeader("Authorization", "Bearer $authToken")
            .build()
        return chain.proceed(request)
    }
}

val authInterceptor = AuthInterceptor("your-auth-token")
val authClient = OkHttpClient.Builder()
    .addInterceptor(authInterceptor)
    .build()

By adding the AuthInterceptor, you streamline authentication headers across requests.

Conclusion

Incorporating headers and interceptors in Retrofit enhances manageability and reusability in your project setup. It allows for adding essential request data such as authentication tokens, transforming requests and responses, and implementing logging for debugging purposes. With these tools, you've additional means to handle complex scenarios and optimize communications with your API efficiently.

Real-world applications extensively benefit from these techniques. Practice by setting up a sample project or implementing these tactics in your existing projects to fully understand their dynamic potential.

Next Article: How to Work with APIs in Kotlin

Previous Article: Using Retrofit with Coroutines for Simplified Networking in Kotlin

Series: Networking in Kotlin

Kotlin

You May Also Like

  • How to Use Modulo for Cyclic Arithmetic in Kotlin
  • Kotlin: Infinite Loop Detected in Code
  • Fixing Kotlin Error: Index Out of Bounds in List Access
  • Setting Up JDBC in a Kotlin Application
  • Creating a File Explorer App with Kotlin
  • How to Work with APIs in Kotlin
  • What is the `when` Expression in Kotlin?
  • Writing a Script to Rename Multiple Files Programmatically in Kotlin
  • Using Safe Calls (`?.`) to Avoid NullPointerExceptions in Kotlin
  • Chaining Safe Calls for Complex Operations in Kotlin
  • Using the Elvis Operator for Default Values in Kotlin
  • Combining Safe Calls and the Elvis Operator in Kotlin
  • When to Avoid the Null Assertion Operator (`!!`) in Kotlin
  • How to Check for Null Values with `if` Statements in Kotlin
  • Using `let` with Nullable Variables for Scoped Operations in Kotlin
  • Kotlin: How to Handle Nulls in Function Parameters
  • Returning Nullable Values from Functions in Kotlin
  • Safely Accessing Properties of Nullable Objects in Kotlin
  • How to Use `is` for Nullable Type Checking in Kotlin