Android-CleanArchitecture-Kotlin
Android-CleanArchitecture-Kotlin copied to clipboard
How should we pass new CoroutineContext to UseCase
Or in general, what modifications should be implemented to support new CoroutineContext in UseCase and from calling side ?
I'd assume all you need to do is make sure the Usecase function is suspend so that you can call it from any coroutine. Considering that ViewModel is typically the one who owns said CoroutineScope.
Let me try it like this,
I'm ok with ViewMmodel being the owner, the question is should it be like:
abstract class UseCase<out Type, in Params> where Type : Any {
abstract suspend fun run(params: Params): Either<Failure, Type>
operator fun invoke(params: Params, coroutineDispatcher: CoroutineDispatcher, job: Job,
onResult: (Either<Failure, Type>) -> Unit = {}) {
val scope = CoroutineScope(coroutineDispatcher + job)
scope.launch {
onResult(run(params))
}
}
class None
}
and from viewModel send/provide::
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
getBooks.invoke(GetBooks.Params("e-book-fiction"), Dispatchers.IO, job) { it.either(::handleError, ::handleBooks) }
@miroslavign I refactored the UseCase class like this:
abstract class UseCase<out Type, in Params> where Type : Any {
abstract suspend fun run(params: Params): Result<Type>
operator fun invoke(params: Params, job: Job, onResult: (Result<Type>) -> Unit = {}) {
val backgroundJob = CoroutineScope(job + Dispatchers.IO).async { run(params) }
CoroutineScope(job + Dispatchers.Main).launch { onResult(backgroundJob.await()) }
}
class None
}
I decided not to pass a CoroutineDispatcher as a method parameter. You can easily set a CoroutineScope based on a Job object, for example job + Dispatchers.Main. I'm not sure (I've not tested it yet) if this implementation would cancel the background task based on coroutine scope, but i cancel a job manually anyway inside OnCleared method of my base ViewModel in this way:
override fun onCleared() { job.cancel() super.onCleared() }
I also replaced Either with Result class (simpler implementation), but this solution should works for both cases.