How to use coroutine LiveData in Android

Issue #358

app/build.gradle

1
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha01"
1
2
3
4
5
6
7
8
9
10
11
12
13
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import kotlinx.coroutines.Dispatchers

class MainViewModel : ViewModel() {
val repository: TodoRepository = TodoRepository()

val firstTodo = liveData(Dispatchers.IO) {
val retrivedTodo = repository.getTodo(1)

emit(retrivedTodo)
}
}

Use coroutines with LiveData

https://developer.android.com/topic/libraries/architecture/coroutines

The liveData building block serves as a structured concurrency primitive between coroutines and LiveData. The code block starts executing when LiveData becomes active and is automatically canceled after a configurable timeout when the LiveData becomes inactive.

Source code

https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt

CoroutineLiveData.kt

1
2
3
4
5
6
@UseExperimental(ExperimentalTypeInference::class)
fun <T> liveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
@BuilderInference block: suspend LiveDataScope<T>.() -> Unit
): LiveData<T> = CoroutineLiveData(context, timeoutInMs, block)

a LiveData that tries to load the User from local cache first and then tries from the server and also yields the updated value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
val user = liveData {
// dispatch loading first
emit(LOADING(id))
// check local storage
val cached = cache.loadUser(id)

if (cached != null) {
emit(cached)
}

if (cached == null || cached.isStale()) {
val fresh = api.fetch(id) // errors are ignored for brevity
cache.save(fresh)
emit(fresh)
}
}

Read more

Comments