NetworkResponseCallAdapter 에서 Call<T>를 Call<NetworkResponse<T>> 로 변환하는 어댑터를 생성했다.
근데 모든 api호출 응답을 NetworkResponse<T>로 바꾸고 싶은건 아니어서,,
이렇게 어댑터 추가하면 다른 응답 타입으로 정의된 콜들은 어떻게 되는건지 걱정됨;;
내가 새로 구현한 NetworkResponseCallAdapter 는
반환타입이 Call<NetworkResponse> 인 Api 호출에만 적용이 된다.
다른 반환 타입을 가진 api들은 NetworkResponseCallAdapter의 영향을 받지 않고, Retrofit에 등록된 다른 CallAdapter (또는 기본 CallAdapter)에 의해 처리된다.
/ NetworkResponseCallAdapterFactory.kt (간략화된 예시)
override fun get(
returnType: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
// 1. 반환 타입이 Call<T> 형태인지 확인
if (getRawType(returnType) != Call::class.java) {
return null // Call<T>가 아니면 우리 어댑터는 처리 안 함
}
// 2. Call<T>의 제네릭 파라미터 T가 NetworkResponse<R> 형태인지 확인
val callInnerType = getParameterUpperBound(0, returnType as ParameterizedType)
if (getRawType(callInnerType) != NetworkResponse::class.java) {
return null // Call 안의 타입이 NetworkResponse<R>이 아니면 우리 어댑터는 처리 안 함
}
// 3. NetworkResponse<R>의 제네릭 파라미터 R (실제 응답 데이터 타입) 추출
val responseType = getParameterUpperBound(0, callInnerType as ParameterizedType)
return NetworkResponseCallAdapter<Any>(responseType) // Any 대신 실제 R 타입 사용
}
interface MyApiService {
// 이 메소드는 NetworkResponseCallAdapter에 의해 처리될 가능성이 높음
@GET("some/data")
fun getMyData(): Call<NetworkResponse<MyActualData>>
// 이 메소드는 NetworkResponseCallAdapter가 null을 반환하고,
// 다른 CallAdapter (예: RxJava용 또는 기본 CallAdapter)에 의해 처리됨
@GET("user/{id}")
fun getUser(@Path("id") id: String): Call<User>
// suspend 함수와 일반 타입을 사용하는 경우 (내부적으로 Call<User>로 변환 후 처리)
@GET("user/profile")
suspend fun getUserProfile(): User // 이 또한 NetworkResponseCallAdapter가 처리하지 않음
// RxJava Observable을 반환하는 경우
@GET("items")
fun getItems(): Observable<List<Item>> // RxJavaCallAdapterFactory가 처리
}
getMyData()
: 반환 타입이 Call<NetworkResponse<MyActualData>>
이므로 NetworkResponseCallAdapterFactory
가 이를 인식하고 NetworkResponseCallAdapter
를 제공하여 NetworkResponse
로 래핑된 결과를 처리합니다.getUser()
: 반환 타입이 Call<User>
입니다. NetworkResponseCallAdapterFactory
의 get()
메소드는 이 타입을 보고 자신이 처리할 수 없다고 판단하여 null
을 반환합니다. 그러면 Retrofit은 다음으로 등록된 CallAdapter.Factory
에게 처리를 위임합니다. 만약 다른 커스텀 어댑터가 없다면, Retrofit의 기본 CallAdapter
가 Call<User>
를 처리하게 됩니다.getUserProfile()
: suspend
함수는 내부적으로 Retrofit에 의해 Call<User>
와 유사하게 처리됩니다. 이 역시 NetworkResponseCallAdapterFactory
의 대상이 아닙니다.getItems()
: Observable<List<Item>>
을 반환하면, RxJava3CallAdapterFactory
(또는 RxJava2 버전)가 등록되어 있다면 해당 팩토리가 이를 처리합니다. NetworkResponseCallAdapter는 명시적으로 NetworkResponse를 반환 타입으로 사용하는 API 호출에만 선택적으로 적용됨!!
다른 반환 타입을 가진 API들은 해당 타입에 맞는 다른 CallAdapter (또는 Retrofit의 기본 동작)에 의해 정상적으로 처리됨.
따라서 하나의 Retrofit 인스턴스 내에서 NetworkResponse를 사용하는 API와 그렇지 않은 기존 방식의 API들을 함께 사용할 수 있습니다. 이는 Retrofit의 유연한 CallAdapter 아키텍처 덕분 😊