androidengineers.Book a session

Architecture & Data

Networking with Retrofit

article55 minHard

Retrofit is a popular Android library for calling HTTP APIs. It turns API endpoints into Kotlin interfaces, which makes networking code easier to read and test.

API Interface

Start by defining the response model.

data class UserDto(
    val id: Int,
    val name: String,
    val email: String
)

Then define the API.

interface UserApi {
    @GET("users")
    suspend fun getUsers(): List<UserDto>

    @GET("users/{id}")
    suspend fun getUser(@Path("id") id: Int): UserDto
}

Retrofit uses annotations like @GET, @POST, @Path, and @Query to build requests.

Creating Retrofit

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

val api = retrofit.create(UserApi::class.java)

Add an OkHttp logging interceptor during development. It prints every request and response to Logcat so you can see exactly what is being sent and received.

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(
        HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }
    )
    .build()

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

Disable the logging interceptor in release builds. It is a development tool and can expose sensitive data.

In real apps, create Retrofit through dependency injection and reuse one instance.

Repository

Keep API calls out of composables.

class UserRepository(
    private val api: UserApi
) {
    suspend fun getUsers(): List<User> {
        return api.getUsers().map { dto ->
            User(dto.id, dto.name, dto.email)
        }
    }
}

The ViewModel talks to the repository, not directly to Retrofit.

Error Handling

Network calls can fail because of no internet, server errors, timeouts, or invalid responses.

Use try/catch and expose meaningful UI state. Distinguish between network errors and HTTP errors.

try {
    val users = repository.getUsers()
    _state.update { it.copy(users = users, isLoading = false) }
} catch (e: IOException) {
    // No internet or connection dropped
    _state.update { it.copy(error = "Check your connection", isLoading = false) }
} catch (e: HttpException) {
    // Server returned 4xx or 5xx
    _state.update { it.copy(error = "Server error: ${e.code()}", isLoading = false) }
}

IOException means the device could not reach the server. HttpException means the server responded but with an error code like 401 (unauthorized) or 500 (server error).

Practice

Create a Retrofit interface for a posts API. Add a repository function that returns posts and a ViewModel that exposes loading, success, and error states.

Summary

Retrofit makes API calls declarative. Keep networking in API and repository layers, map DTOs to app models, and always handle failure.

YOUR LEARNING JOURNEY

0 of 22 available lessons completed

Progress saved in this browser. No account needed.
Networking with Retrofit | Junior Android Developer | Android Engineers