Skip to content

Android Retrofit Networking

Retrofit is the standard HTTP client for Android, converting REST API definitions into Kotlin interfaces. Combined with Gson for JSON parsing and OkHttp for transport, it provides type-safe API access with minimal boilerplate.

Key Facts

  • Retrofit converts annotated Kotlin interfaces into HTTP client implementations
  • @GET, @POST, @PUT, @DELETE define HTTP methods on interface functions
  • @Path("id") substitutes into URL path segments ({id})
  • @Query("name") appends URL query parameters
  • GsonConverterFactory handles JSON serialization/deserialization
  • OkHttpClient with logging interceptor enables network debugging
  • Returns can be Observable<T> (RxJava), Call<T>, or suspend functions (coroutines)

Patterns

Data Models

data class GeckoCoin(
    val id: String,
    val symbol: String,
    val name: String,
    val image: String,
    val current_price: Float,
    val market_cap: Float,
    val market_cap_rank: Int,
    val total_volume: Float,
    val price_change_percentage_24h: Float
)

data class GeckoCoinChart(
    var prices: List<List<Float>>
)

API Interface

import retrofit2.http.*

interface CoinGeckoApi {
    @GET("coins/markets")
    fun getCoinMarket(
        @Query("vs_currency") vs: String = "usd",
        @Query("per_page") perPage: Int = 100,
        @Query("sparkline") sparkline: Boolean = false,
        @Query("order") order: String = "market_cap_desc"
    ): Observable<List<GeckoCoin>>

    @GET("coins/{id}/market_chart")
    fun getCoinMarketChart(
        @Path("id") id: String,
        @Query("vs_currency") vsCurrency: String = "usd",
        @Query("days") days: String = "max"
    ): Observable<GeckoCoinChart>
}

Retrofit Annotations Reference

Annotation Purpose Example
@GET("path") GET request @GET("coins/markets")
@POST("path") POST request @POST("users")
@PUT("path") PUT request @PUT("users/{id}")
@DELETE("path") DELETE request @DELETE("users/{id}")
@Path("name") URL path parameter {id} in URL
@Query("name") Query parameter ?key=value
@QueryMap Multiple query params Map<String, String>
@Body Request body For POST/PUT

Retrofit Builder

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(
        HttpLoggingInterceptor()
            .setLevel(HttpLoggingInterceptor.Level.BODY)
    )
    .connectTimeout(60, TimeUnit.SECONDS)
    .build()

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.coingecko.com/api/v3/")
    .addConverterFactory(GsonConverterFactory.create(gson))
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .client(okHttpClient)
    .build()

val apiService = retrofit.create(CoinGeckoApi::class.java)

With Dagger 2 Module

@Module
class RestModule {
    @Provides
    @Singleton
    fun provideGson(): Gson = GsonBuilder().setLenient().create()

    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient =
        OkHttpClient.Builder()
            .addInterceptor(
                HttpLoggingInterceptor()
                    .setLevel(HttpLoggingInterceptor.Level.BODY)
            )
            .connectTimeout(60, TimeUnit.SECONDS)
            .build()

    @Provides
    @Singleton
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit =
        Retrofit.Builder()
            .baseUrl("https://api.coingecko.com/api/v3/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            .build()

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): CoinGeckoApi =
        retrofit.create(CoinGeckoApi::class.java)
}

Retrofit vs URLSession (iOS) Comparison

Feature Retrofit (Android) URLSession (iOS)
Definition Annotated interface Inline URL construction
JSON parsing Gson converter JSONDecoder (Codable)
Type safety Compile-time from annotations Runtime from Decodable
HTTP client OkHttp Built-in URLSession
Async RxJava / Coroutines async/await

build.gradle Dependencies

implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.google.code.gson:gson:2.10.0"
implementation "com.squareup.okhttp3:okhttp:4.11.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"

Gotchas

  • Base URL must end with / or Retrofit throws an exception
  • @Path parameters are URL-encoded by default; use @Path(encoded = true) for pre-encoded values
  • Logging interceptor at Level.BODY logs full request/response bodies - disable in production for security
  • Gson uses field names by default for JSON keys; use @SerializedName("json_key") for custom mapping
  • Network calls on the main thread cause NetworkOnMainThreadException - always use background dispatchers
  • Observable<T> requires RxJava2CallAdapterFactory; for coroutines, use suspend fun return types instead

See Also