Learn Kotlin Coroutines for Android by example
Article: Android Coroutine Recipes
Slides: Android Coroutine Recipes
Contains following examples:
- How to launch a coroutine
- How to launch coroutine with a timeout
- How to launch coroutine which perform 2 background tasks sequentially
- How to launch coroutine which perform 2 background tasks in parallel
- How to cancel a coroutine
- How to catch exception thrown inside coroutine (try/catch)
- How to catch exception thrown inside coroutine (exception handler)
- Lifecycle Aware Coroutine - Lifecycle Observer
- Lifecycle Aware Coroutine - Scoped Fragment
How to launch a coroutine
fun loadData() = GlobalScope.launch(uiContext + job) {
showLoading() // ui thread
val result = dataProvider.loadData() // non ui thread, suspend until finished
showText(result) // ui thread
hideLoading() // ui thread
}
You can get full code here
How to launch coroutine with a timeout
fun loadData() = GlobalScope.launch(uiContext + job) {
showLoading()
val result = withTimeoutOrNull(1, TimeUnit.SECONDS) { dataProvider.loadData() }
showText(result ?: "Timeout")
hideLoading()
}
You can get full code here
How to launch coroutine which perform 2 background tasks sequentially
fun loadData() = GlobalScope.launch(uiContext + job) {
showLoading()
val result1 = dataProvider.loadData()
val result2 = dataProvider.loadData()
showText("$result1\n$result2")
hideLoading()
}
You can get full code here
How to launch coroutine which perform 2 background tasks in parallel
fun loadData() = GlobalScope.launch(uiContext + job) {
showLoading()
val result1 = async { dataProvider.loadData() }
val result2 = async { dataProvider.loadData() }
val data = "${result1.await()}\n${result2.await()}"
showText(data)
hideLoading()
}
You can get full code here
How to cancel a coroutine
private var job: Job = Job()
fun loadData() = GlobalScope.launch(uiContext + job) {
...
}
override fun onDestroyView() {
super.onDestroyView()
job.cancel()
}
You can get full code here
source
How to catch exception thrown inside coroutine (try/catch)fun loadData() = GlobalScope.launch(uiContext + job) {
showLoading()
try {
val result = dataProvider.loadData()
showText(result)
} catch (e: IllegalArgumentException) {
showText(e.message ?: "")
}
hideLoading()
}
You can get full code here
How to catch exception thrown inside coroutine (exception handler)
val exceptionHandler: CoroutineContext = CoroutineExceptionHandler { _, throwable ->
showText(throwable.message ?: "")
hideLoading()
job = Job() // exception handler cancels job
}
// we can attach CoroutineExceptionHandler to parent context
fun loadData() = GlobalScope.launch(uiContext + job + exceptionHandler) {
...
}
You can get full code here
Lifecycle Aware Coroutine - Lifecycle Observer
You can get full code here
class MainScope : CoroutineScope, LifecycleObserver {
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onCreate() {
job = Job()
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun destroy() = job.cancel()
}
class MyFragment : ScopedFragment() {
private val mainScope = MainScope()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(mainScope)
}
private fun loadData() = mainScope.launch {
...
}
}
Lifecycle Aware Coroutine - Scoped Fragment
You can get full code here
abstract class ScopedFragment : Fragment(), CoroutineScope {
protected lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
job = Job()
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
class MyFragment : ScopedFragment() {
private fun loadData() = launch {
...
}
}