Learning and Using Retrofit in Android
Overview
Retrofit is a RESTful network request framework for Android. Under the hood, it relies on OkHttp for actual HTTP communication while providing a clean abstraction layer for API interface definitions. Retrofit handles request parameters, headers, URLs, and response parsing through annotated interface methods.
Benefits
Comparing with raw OkHttp usage, several pain points emerge:
- Tedious interface configuration, especially when handling request bodies, headers, and multiple parameters
- Manual response body parsing that lacks reusability across different endpoints
- No automatic thread switching for UI updates
Retrofit addresses these issues by providing a declarative interface-based approach to network calls.
Implementation
Important: Ensure the BaseUrl ends with a forward slash, otherwise an exception will be thrown. The following demonstrates a GET request example. Endpoint: ${BASE_URL}test?name=" "&age=""
3.1 API Interface
Define the network endpoint contract with annotated method signatures:
interface UserApiService {
@GET("test")
suspend fun fetchUser(
@Query("name") userName: String,
@Query("age") userAge: String
): ApiResponse<List<User>>
}
User data model:
data class User(
val name: String = "",
val age: String = ""
)
Standardized response wrapper:
data class ApiResponse<T>(
val code: String,
val data: T
)
3.2 RetrofitManager
Configure OkHttpClient instance and build Retrofit with required converters and base URL:
private val httpClient: OkHttpClient
get() = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.build()
fun <T> createService(serviceClass: Class<T>, baseUrl: String? = null): T {
return Retrofit.Builder()
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
.create(serviceClass)
}
3.3 DataRepository
Implement the API interface and provide a centralized access point for network operations:
object NetworkRepository : UserApiService {
private val apiInstance by lazy { RetrofitManager.createService(UserApiService::class.java) }
override suspend fun fetchUser(
userName: String,
userAge: String
): ApiResponse<List<User>> {
return apiInstance.fetchUser(userName, userAge)
}
}
3.4 ViewModel Integration
Execute network requests within coroutine scope for proper lifecycle management:
fun loadUserData(name: String, age: String) {
viewModelScope.launch {
val response = NetworkRepository.fetchUser(name, age)
Log.d("network", "result: $response")
}
}
3.5 UI Layer Call
loadUserData("", "")