← All courses

Networking with Retrofit

🗓 May 31, 2026 ⏱ 2 min read

Why a networking library?

Almost every real app talks to a server: logging in, fetching a feed, posting data. You could use raw sockets, but that is painful. Retrofit (by Square) is the standard library that turns a REST API into a simple Kotlin interface, and pairs with a converter (Moshi or Gson) to parse JSON into objects automatically.

Step 1: the data model

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

Step 2: describe the API

interface ApiService {
    @GET("users")
    suspend fun getUsers(): List<User>

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

    @POST("users")
    suspend fun createUser(@Body user: User): User
}

Each annotation (@GET, @POST, @Path, @Body) maps a Kotlin function to an HTTP request. The suspend keyword means it runs off the main thread.

Step 3: build Retrofit

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

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

Step 4: call it safely

viewModelScope.launch {
    try {
        val users = api.getUsers()          // background thread
        _uiState.value = UiState.Success(users)
    } catch (e: IOException) {
        _uiState.value = UiState.Error("No internet")
    } catch (e: HttpException) {
        _uiState.value = UiState.Error("Server error ${e.code()}")
    }
}

Don’t forget the permission

<uses-permission android:name="android.permission.INTERNET" />

Common mistakes

  • Calling the network on the main thread — always use suspend + a coroutine.
  • Not handling errors — networks fail; wrap calls in try/catch and show a message.
  • Forgetting the trailing slash in baseUrl (Retrofit requires it).
Summary: Describe the API in an interface, build Retrofit with a JSON converter, call suspend functions inside a coroutine, and always handle errors.