How to convert any callback to Coroutines and use them in Kotlin Android?
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 -> { _apiLiveData.value = Resource.success("") } is ApiUseCase.Result.Failed -> { _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.
I am a very enthusiastic Android developer to build solid Android apps. I have a keen interest in developing for Android and have published apps to the Google Play Store. I always open to learning new technologies. For any help drop us a line anytime at contact@mobologicplus.com