|

How to convert any callback to Coroutines and use them in Kotlin Android?

Sharing is caring!

Hello everyone,

In this article, we are going to learn something to handle the callback by using Kotlin Coroutines. As we are already familiar with Coroutines in my earlier post here get started Coroutines. Alright, then let’s started to learn about the deal with callback in coroutines. 

In android, we mostly use the UseCase to deal with API calls. Generally use case is very useful and provides a safe mechanism to call. I am not going into the deep here. Whenever we hit the API in the use case implementation, we need a callback to check the status of the APIs is either successful or failed.

Let’s take an example to understand the flow. 

interface ApiUseCase {

    suspend fun hitApi(): Result

    sealed class Result {
        data class Success(val result: String) : Result()
        data class Failed(val message: String, val errorCode: Int) : Result()
    }
}

Here I created an Interface of UseCase and a suspend function which is using the Coroutines feature and I want a Result callback either success or failed. Now we need to implement this interface to use this function.

class ApiUseCaseImp : ApiUseCase {

    override suspend fun hitApi(): ApiUseCase.Result =
        withContext(Dispatchers.IO) {
            suspendCoroutine<ApiUseCase.Result> { coroutines -> 
                RetroFitCall() { response ->
                    when (response.responseCode) {
                        200 -> {
                            coroutines.resume(ApiUseCase.Result.Success(""))
                        }
                        else -> {
                            coroutines.resume(
                                ApiUseCase.Result.Failed(
                                    "error message", response.errorCode
                                )
                            )
                        }
                    }
                }
            }
        }

}

Here we use suspendCoroutine as the return block to deal with resume the result back to us either result success of failed. Now lets check how to check the callback result in Coroutines scope. I am assume every one use the ViewModel to call this api. 

class ApiViewModel(private val useCase: ApiUseCase) : ViewModel() {

    private val _apiLiveData = SingleLiveEvent<Resource<String>>()
    val apiLiveData: SingleLiveEvent<Resource<String>>
        get() = _apiLiveData


    fun callApi() {
        viewModelScope.launch {
            _apiLiveData.value = Resource.loading(null)
            when (val result = useCase.hitApi()) {
                is ApiUseCase.Result.Success -> {
                    _apiLiveData.value = Resource.success("")
                }
                is ApiUseCase.Result.Failed -> {
                    _apiLiveData.value = Resource.error(result.message, null, result.errorCode)
                }
            }
        }
    }

Here we use the coroutines scope with Launch function to call the api and check the status of api. As we know Coroutines also provide the feature to cancel the Job if it is required to cancel the api call in between. In this case we need to stop the thread and free the resource.

class ApiViewModel(private val useCase: ApiUseCase) : ViewModel() {

   private val _apiLiveData = SingleLiveEvent<Resource<String>>() 
   val apiLiveData: SingleLiveEvent<Resource<String>> 
   get() = _apiLiveData

   private var apiJob: Job? = null

    fun callApi() {
        apiJob = viewModelScope.launch {
            _apiLiveData.value = Resource.loading(null)
            when (val result = useCase.hitApi()) {
                is ApiUseCase.Result.Success -&gt; {
                    _apiLiveData.value = Resource.success("")
                }
                is ApiUseCase.Result.Failed -&gt; {
                    _apiLiveData.value = Resource.error(result.message, null, result.errorCode)
                }
            }
        }
    }

fun cancelApiJob() {
    if (apiJob != null && apiJob?.isActive == true) {
         apiJob?.cancel()
    }
}

So, today we learned how to convert any callback to Coroutines and use them. That is all for this. Thanks for reading this article.

0 0 votes
Article Rating

Similar Posts

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments