Issue #358

app/build.gradle

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha01"
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

@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

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