Skip to content

Commit

Permalink
feature: Create Retrofit CallAdapter to convert the Response to ApiRe…
Browse files Browse the repository at this point in the history
…sult in the interface
  • Loading branch information
ShivamNagpal committed Mar 25, 2023
1 parent 601c2d8 commit 3c322a1
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.nagpal.shivam.vtucslab.retrofit

import com.nagpal.shivam.vtucslab.retrofit.ApiResult.ApiException
import okhttp3.Request
import okio.Timeout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class ApiResultCall<T : Any>(private val proxy: Call<T>) : Call<ApiResult<T>> {
override fun enqueue(callback: Callback<ApiResult<T>>) {
proxy.enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
val apiResult = handleApiResult { response }
callback.onResponse(this@ApiResultCall, Response.success(apiResult))
}

override fun onFailure(call: Call<T>, t: Throwable) {
val apiResult = ApiException<T>(t)
callback.onResponse(this@ApiResultCall, Response.success(apiResult))
}
})
}

override fun execute(): Response<ApiResult<T>> = throw NotImplementedError()

override fun clone(): Call<ApiResult<T>> = ApiResultCall(proxy.clone())

override fun isExecuted(): Boolean = proxy.isExecuted

override fun cancel() = proxy.cancel()

override fun isCanceled(): Boolean = proxy.isCanceled

override fun request(): Request = proxy.request()

override fun timeout(): Timeout = proxy.timeout()

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.nagpal.shivam.vtucslab.retrofit

import retrofit2.Call
import retrofit2.CallAdapter
import java.lang.reflect.Type

class ApiResultCallAdapter(private val resultType: Type) :
CallAdapter<Type, Call<ApiResult<Type>>> {
override fun responseType(): Type = resultType

override fun adapt(call: Call<Type>): Call<ApiResult<Type>> {
return ApiResultCall(call)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.nagpal.shivam.vtucslab.retrofit

import retrofit2.Call
import retrofit2.CallAdapter
import retrofit2.Retrofit
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class ApiResultCallAdapterFactory private constructor() : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
if (getRawType(returnType) != Call::class.java) {
return null
}

val callType = getParameterUpperBound(0, returnType as ParameterizedType)
if (getRawType(callType) != ApiResult::class.java) {
return null
}

val resultType = getParameterUpperBound(0, callType as ParameterizedType)
return ApiResultCallAdapter(resultType)
}

companion object {
fun create(): ApiResultCallAdapterFactory = ApiResultCallAdapterFactory()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import com.nagpal.shivam.vtucslab.retrofit.ApiResult.*
import retrofit2.HttpException
import retrofit2.Response

suspend fun <T : Any> handleApi(
execute: suspend () -> Response<T>
fun <T : Any> handleApiResult(
execute: () -> Response<T>
): ApiResult<T> {
return try {
val response = execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.nagpal.shivam.vtucslab.VTUCSLabApplication
import com.nagpal.shivam.vtucslab.retrofit.ApiResult.*
import com.nagpal.shivam.vtucslab.retrofit.handleApi
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultError
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultException
import com.nagpal.shivam.vtucslab.services.VtuCsLabService
Expand Down Expand Up @@ -46,8 +45,7 @@ class DisplayViewModel(app: Application) : AndroidViewModel(app) {
}
_uiState.update { initialState }
viewModelScope.launch(Dispatchers.IO) {
when (val networkResult =
handleApi { VtuCsLabService.instance.fetchRawResponse(url) }) {
when (val networkResult = VtuCsLabService.instance.fetchRawResponse(url)) {
is ApiSuccess -> {
_uiState.update {
val stringResponse = networkResult.data.replace("\t", "\t\t")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.nagpal.shivam.vtucslab.VTUCSLabApplication
import com.nagpal.shivam.vtucslab.retrofit.ApiResult.*
import com.nagpal.shivam.vtucslab.retrofit.handleApi
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultError
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultException
import com.nagpal.shivam.vtucslab.services.VtuCsLabService
Expand Down Expand Up @@ -45,10 +44,8 @@ class ProgramViewModel(app: Application) : AndroidViewModel(app) {
}
_uiState.update { initialState }
viewModelScope.launch(Dispatchers.IO) {
val networkResult =
handleApi { VtuCsLabService.instance.getLaboratoryExperimentsResponse(url) }

when (networkResult) {
when (val networkResult =
VtuCsLabService.instance.getLaboratoryExperimentsResponse(url)) {
is ApiSuccess -> {
_uiState.update {
val labResponse = networkResult.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.nagpal.shivam.vtucslab.VTUCSLabApplication
import com.nagpal.shivam.vtucslab.retrofit.ApiResult.*
import com.nagpal.shivam.vtucslab.retrofit.handleApi
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultError
import com.nagpal.shivam.vtucslab.retrofit.logNetworkResultException
import com.nagpal.shivam.vtucslab.services.VtuCsLabService
Expand Down Expand Up @@ -45,9 +44,7 @@ class RepositoryViewModel(app: Application) : AndroidViewModel(app) {
}
_uiState.update { initialState }
viewModelScope.launch(Dispatchers.IO) {

when (val networkResult =
handleApi { VtuCsLabService.instance.getLaboratoryResponse(url) }) {
when (val networkResult = VtuCsLabService.instance.getLaboratoryResponse(url)) {
is ApiSuccess -> {
_uiState.update {
val labResponse = networkResult.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ package com.nagpal.shivam.vtucslab.services

import com.nagpal.shivam.vtucslab.models.LaboratoryExperimentResponse
import com.nagpal.shivam.vtucslab.models.LaboratoryResponse
import com.nagpal.shivam.vtucslab.retrofit.ApiResult
import com.nagpal.shivam.vtucslab.utilities.Constants
import com.nagpal.shivam.vtucslab.utilities.StaticMethods
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Url

interface VtuCsLabService {

@GET
suspend fun getLaboratoryResponse(@Url url: String): Response<LaboratoryResponse>
suspend fun getLaboratoryResponse(@Url url: String): ApiResult<LaboratoryResponse>

@GET
suspend fun getLaboratoryExperimentsResponse(@Url url: String): Response<LaboratoryExperimentResponse>
suspend fun getLaboratoryExperimentsResponse(@Url url: String): ApiResult<LaboratoryExperimentResponse>

@GET
suspend fun fetchRawResponse(@Url url: String): Response<String>
suspend fun fetchRawResponse(@Url url: String): ApiResult<String>

companion object {
val instance: VtuCsLabService by lazy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import com.nagpal.shivam.vtucslab.models.LaboratoryExperimentResponse
import com.nagpal.shivam.vtucslab.models.LaboratoryResponse
import com.nagpal.shivam.vtucslab.retrofit.ApiResultCallAdapterFactory
import retrofit2.Retrofit
import retrofit2.converter.jackson.JacksonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
Expand All @@ -24,6 +25,7 @@ object StaticMethods {
return Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(JacksonConverterFactory.create(jsonMapper))
.addCallAdapterFactory(ApiResultCallAdapterFactory.create())
}

fun getBaseURL(labResponse: LaboratoryResponse): String {
Expand Down

0 comments on commit 3c322a1

Please sign in to comment.