Reputation: 620
I am using retofit service without using callback. So, its probably going with Kotlin Coroutine suspend fun
. I referred many blogs, mediums and so many tutorials. Well this is easy to get response using coroutine scope
with IO and Main
thread.
So, after referring some examples I am considers to do code like this:
Restrofit Service Interface RetrofitInterfaces.kt
:
interface RetrofitInterfaces {
@FormUrlEncoded
@POST("get-videos-pagination")
suspend fun getTemplates(@Field("app_name") app_name: String,
@Field("sort_by") sortBy: String,
@Field("video_loaded_ids") loadedIds: String): Response<Model_Video_List>
}
Where Model_Video_List.kt
class is my response data class.
Retrofit Builder RetrofitClient.kt
:
object RetrofitClient {
fun makeRetrofitService(mContext: Context): RetrofitInterfaces {
val gson = GsonBuilder().setLenient().create()
return Retrofit.Builder()
.baseUrl(AppPreferences.getBaseUrl(mContext) + "/api/v3/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build().create(RetrofitInterfaces::class.java)
}
}
Here I am using Gson
to serialise
or deserialise
Json data
.
Now what is problematic and where problem started in to get error response I am using ResultWrapper.kt
:
class ResultWrapper {
enum class ErrorCode {
NETWORK,// Connection failed or timeout
SERVER,// Server errors due to maintenance or over request
INVALID// Response is success but can't serialised with Data Class!
}
interface ResponseWrapper {
suspend fun onSuccess(response: Response<Any>)
suspend fun onFailure(eCode: ErrorCode)
}
private var responseWrapper: ResponseWrapper? = null
set
suspend fun enqueue(response: Response<Any>, responseWrapper: ResponseWrapper) {
this.responseWrapper = responseWrapper
if (response.isSuccessful) {
responseWrapper.onSuccess(response)
} else {
val errorCode = response.code()
when (errorCode) {
in 200..299 -> {
responseWrapper.onFailure(ErrorCode.INVALID)
}
in 400..499 -> {
responseWrapper.onFailure(ErrorCode.NETWORK)
}
in 500..599 -> {
responseWrapper.onFailure(ErrorCode.SERVER)
}
}
}
}
}
So, now I can call this enqueue fun
from anywhere in app
like:
private fun getVideoList(loadedIds: String, sortBy: String) {
val service = RetrofitClient.makeRetrofitService(mContext)
scope.launch {
val response = service.getTemplates("MyApp", sortBy, loadedIds)
val resultWrapper = ResultWrapper()
resultWrapper.enqueue(response, object : ResultWrapper.ResponseWrapper {
override suspend fun onSuccess(response: Response<Any>) {
}
override suspend fun onFailure(eCode: ResultWrapper.ErrorCode) {
}
})
}
}
But I am getting compile error
for passing response
in resultWrapper.enqueue()
because in ResultWrapper.ResponseWrapper interface
there is method defined with suspend fun onSuccess(response: Response<Any>)
. So, type conversion problem occurred here!
If Retrofit CallBack<T>
can handle any type of Model or Data classes
and return which is exact tpyed. Like above service requires Model_Video_List
class in response and other services requires there own then what to do for it? Is there only way to use separate function for every service? Or is it only possible in Java?!
Upvotes: 1
Views: 953
Reputation: 20684
You can introduce a generic parameter type T
in your class ResultWrapper
, so whenever you create an instance of this class you must specify an actual type in place of T
.
Change your ResultWrapper
to this:
class ResultWrapper<T> {
enum class ErrorCode {
NETWORK,// Connection failed or timeout
SERVER,// Server errors due to maintenance or over request
INVALID// Response is success but can't serialised with Data Class!
}
interface ResponseWrapper<T> {
suspend fun onSuccess(response: Response<T>)
suspend fun onFailure(eCode: ErrorCode)
}
private var responseWrapper: ResponseWrapper<T>? = null
set
suspend fun enqueue(response: Response<T>, responseWrapper: ResponseWrapper<T>) {
this.responseWrapper = responseWrapper
if (response.isSuccessful) {
responseWrapper.onSuccess(response)
} else {
val errorCode = response.code()
when (errorCode) {
in 200..299 -> {
responseWrapper.onFailure(ErrorCode.INVALID)
}
in 400..499 -> {
responseWrapper.onFailure(ErrorCode.NETWORK)
}
in 500..599 -> {
responseWrapper.onFailure(ErrorCode.SERVER)
}
}
}
}
}
And also change your method to this:
private fun getVideoList(loadedIds: String, sortBy: String) {
val service = RetrofitClient.makeRetrofitService(mContext)
scope.launch {
val response = service.getTemplates("MyApp", sortBy, loadedIds)
val resultWrapper = ResultWrapper<Model_Video_List>()
resultWrapper.enqueue(response, object : ResultWrapper.ResponseWrapper<Model_Video_List> {
override suspend fun onSuccess(response: Response<Model_Video_List>) {
}
override suspend fun onFailure(eCode: ResultWrapper.ErrorCode) {
}
})
}
}
Upvotes: 5