What is the best way to organize coroutines for application in elegant way? I understand, the question seems odd. Let me show the example of Executors
Create an object AppExecutors.kt
object AppExecutors {
private val main: Executor = MainThreadExecutor()
private val util: Executor = Executors.newFixedThreadPool(3)
fun main(f: () -> Unit) {
main.execute(f)
}
fun util(f: () -> Unit) {
util.execute(f)
}
class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable?) {
mainThreadHandler.post(command)
}
}
}
Now, we can use this. Simple, minimal code, etc
val exe = AppExecutors
exe.util {
val first = calculateFirst()
val second = calculateSecond()
val str = ("first = $first | second = $second")
exe.main {
Toast.makeText(activity, "Executors $str", Toast.LENGTH_LONG).show()
}
}
Now, i'v tried to use this approach on coroutines AppCoRoutines.kt
object AppCoRoutines{
private val uiContext: CoroutineContext = Dispatchers.Main
private val ioContext: CoroutineContext = Dispatchers.IO
private val networkContext: CoroutineContext = Executors.newFixedThreadPool(3).asCoroutineDispatcher()
private val singleContext: CoroutineContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
val ui: CoroutineScope = CoroutineScope(uiContext)
val io: CoroutineScope = CoroutineScope(ioContext)
val net: CoroutineScope = CoroutineScope(networkContext)
val single: CoroutineScope = CoroutineScope(singleContext)
}
Now, use this:
val coRout = AppCoRoutines
coRout.ui.launch {
val str: String = withContext(coRout.net.coroutineContext){
val first = async { calculateFirst() }
val second = async { calculateSecond() }
("first = $first | second = $second")
}
Toast.makeText(activity, "CoRoutine $str", Toast.LENGTH_LONG).show()
}
No so elegant at all. Maybe someone could suggest more simple way? I'm not so good in this right now, so i'm using coroutines for just simple taks.
Thank you in advance!
You need to extend
CoroutineScopeon the call-site (where ever you want to use your coroutines, e.g.coRout.ui.launchin the current implementation) of your coroutines. That way, you don't have to write and repeatcoRout.ui.launcheverywhere and also, you can avoid memory leaks in the current code (because your coroutines can be alive whilst your calling object wants to be destroyed)For example, If you are inside a class, you can make your class extend
CoroutineScopelike below:Inside this class, you can use
launchandwithContextto easily handle your coroutines. You can alsocancel()thejobobject when you know your class is being destroyed (likeonDestoryfor android activities), so that all the coroutines for this class get cancelled.