# CoroutineLiveDataKt

Added in 2.7.0

*** ** * ** ***


```
public final class CoroutineLiveDataKt
```

<br />

*** ** * ** ***

## Summary

| ### Public methods |
|---|---|
| `static final @https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveData<@https://developer.android.com/reference/androidx/annotation/NonNull T>` | `<T extends https://developer.android.com/reference/java/lang/Object.html> https://developer.android.com/reference/androidx/lifecycle/CoroutineLiveDataKt#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)( @https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html context, long timeoutInMs, @https://developer.android.com/reference/androidx/annotation/NonNull SuspendFunction1<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveDataScope<@https://developer.android.com/reference/androidx/annotation/NonNull T>, https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html> block )` Builds a LiveData that has values yielded from the given `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` that executes on a `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope`. |
| `static final @https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveData<@https://developer.android.com/reference/androidx/annotation/NonNull T>` | `@https://developer.android.com/reference/androidx/annotation/RequiresApi(value = 26) <T extends https://developer.android.com/reference/java/lang/Object.html> https://developer.android.com/reference/androidx/lifecycle/CoroutineLiveDataKt#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)( @https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/java/time/Duration.html timeout, @https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html context, @https://developer.android.com/reference/androidx/annotation/NonNull SuspendFunction1<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveDataScope<@https://developer.android.com/reference/androidx/annotation/NonNull T>, https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html> block )` Builds a LiveData that has values yielded from the given `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` that executes on a `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope`. |

## Public methods

### liveData

Artifact: [androidx.lifecycle:lifecycle-livedata](https://developer.android.com/jetpack/androidx/releases/lifecycle) [View Source](https://cs.android.com/search?q=file:androidx/lifecycle/CoroutineLiveData.kt+function:liveData) Added in [2.7.0](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.7.0)

```
public static final @NonNull LiveData<@NonNull T> <T extends Object> liveData(
    @NonNull CoroutineContext context,
    long timeoutInMs,
    @NonNull SuspendFunction1<@NonNull LiveDataScope<@NonNull T>, Unit> block
)
```

Builds a LiveData that has values yielded from the given `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` that executes on a `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope`.

The `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` starts executing when the returned `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes LiveData.onActive. If the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes LiveData.onInactive while the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` is executing, it will be cancelled after `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` milliseconds unless the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes active again before that timeout (to gracefully handle cases like Activity rotation). Any value `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#emit(kotlin.Any)`ed from a cancelled `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` will be ignored.

After a cancellation, if the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes active again, the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` will be re-executed from the beginning. If you would like to continue the operations based on where it was stopped last, you can use the `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#latestValue()` function to get the last `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#emit(kotlin.Any)`ed value.

If the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` completes successfully *or* is cancelled due to reasons other than `https://developer.android.com/reference/androidx/lifecycle/LiveData` becoming inactive, it *will not* be re-executed even after `https://developer.android.com/reference/androidx/lifecycle/LiveData` goes through active inactive cycle.

As a best practice, it is important for the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` to cooperate in cancellation. See kotlin coroutines documentation for details https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html.

The `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` can be changed to fit different use cases better, for example increasing it will give more time to the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` to complete even if `https://developer.android.com/reference/androidx/lifecycle/LiveData` is inactive. It is good for cases when `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` is finite (meaning it can complete successfully) and is costly to restart. Otherwise if a `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` is cheap to restart, decreasing the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(kotlin.coroutines.CoroutineContext,kotlin.Long,kotlin.coroutines.SuspendFunction1)` value will allow to yield less values that aren't consumed by anything.

```
// a simple LiveData that receives value 3, 3 seconds after being observed for the first time.
val data : LiveData<Int> = liveData {
    delay(3000)
    emit(3)
}


// a LiveData that fetches a `User` object based on a `userId` and refreshes it every 30 seconds
// as long as it is observed
val userId : LiveData<String> = ...
val user = userId.switchMap { id ->
    liveData {
      while(true) {
        // note that `while(true)` is fine because the `delay(30_000)` below will cooperate in
        // cancellation if LiveData is not actively observed anymore
        val data = api.fetch(id) // errors are ignored for brevity
        emit(data)
        delay(30_000)
      }
    }
}

// A retrying data fetcher with doubling back-off
val user = liveData {
    var backOffTime = 1_000
    var succeeded = false
    while(!succeeded) {
        try {
            emit(api.fetch(id))
            succeeded = true
        } catch(ioError : IOException) {
            delay(backOffTime)
            backOffTime *= minOf(backOffTime * 2, 60_000)
        }
    }
}

// a LiveData that tries to load the `User` from local cache first and then tries to fetch
// 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)
    }
}

// a LiveData that immediately receives a LiveData<User> from the database and yields it as a
// source but also tries to back-fill the database from the server
val user = liveData {
    val fromDb: LiveData<User> = roomDatabase.loadUser(id)
    emitSource(fromDb)
    val updated = api.fetch(id) // errors are ignored for brevity
    // Since we are using Room here, updating the database will update the `fromDb` LiveData
    // that was obtained above. See Room's documentation for more details.
    // https://developer.android.com/training/data-storage/room/accessing-data#query-observable
    roomDatabase.insert(updated)
}
```

| Parameters |
|---|---|
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html context` | The CoroutineContext to run the given block in. Defaults to `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-empty-coroutine-context/index.html` combined with `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-coroutine-dispatcher/immediate.html` |
| `long timeoutInMs` | The timeout in ms before cancelling the block if there are no active observers (`https://developer.android.com/reference/androidx/lifecycle/LiveData#hasActiveObservers()`. Defaults to `https://developer.android.com/reference/androidx/lifecycle/package-summary#DEFAULT_TIMEOUT()`. |
| `@https://developer.android.com/reference/androidx/annotation/NonNull SuspendFunction1<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveDataScope<@https://developer.android.com/reference/androidx/annotation/NonNull T>, https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html> block` | The block to run when the `https://developer.android.com/reference/androidx/lifecycle/LiveData` has active observers. |

### liveData

Artifact: [androidx.lifecycle:lifecycle-livedata](https://developer.android.com/jetpack/androidx/releases/lifecycle) [View Source](https://cs.android.com/search?q=file:androidx/lifecycle/CoroutineLiveData.kt+function:liveData) Added in [2.7.0](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.7.0)

```
@RequiresApi(value = 26)
public static final @NonNull LiveData<@NonNull T> <T extends Object> liveData(
    @NonNull Duration timeout,
    @NonNull CoroutineContext context,
    @NonNull SuspendFunction1<@NonNull LiveDataScope<@NonNull T>, Unit> block
)
```

Builds a LiveData that has values yielded from the given `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` that executes on a `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope`.

The `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` starts executing when the returned `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes LiveData.onActive. If the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes LiveData.onInactive while the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` is executing, it will be cancelled after the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` duration unless the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes active again before that timeout (to gracefully handle cases like Activity rotation). Any value `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#emit(kotlin.Any)`ed from a cancelled `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` will be ignored.

After a cancellation, if the `https://developer.android.com/reference/androidx/lifecycle/LiveData` becomes active again, the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` will be re-executed from the beginning. If you would like to continue the operations based on where it was stopped last, you can use the `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#latestValue()` function to get the last `https://developer.android.com/reference/androidx/lifecycle/LiveDataScope#emit(kotlin.Any)`ed value.

If the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` completes successfully *or* is cancelled due to reasons other than `https://developer.android.com/reference/androidx/lifecycle/LiveData` becoming inactive, it *will not* be re-executed even after `https://developer.android.com/reference/androidx/lifecycle/LiveData` goes through active inactive cycle.

As a best practice, it is important for the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` to cooperate in cancellation. See kotlin coroutines documentation for details https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html.

The `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` can be changed to fit different use cases better, for example increasing it will give more time to the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` to complete even if `https://developer.android.com/reference/androidx/lifecycle/LiveData` is inactive. It is good for cases when `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` is finite (meaning it can complete successfully) and is costly to restart. Otherwise if a `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` is cheap to restart, decreasing the `https://developer.android.com/reference/androidx/lifecycle/package-summary#liveData(java.time.Duration,kotlin.coroutines.CoroutineContext,kotlin.coroutines.SuspendFunction1)` value will allow to yield less values that aren't consumed by anything.

```
// a simple LiveData that receives value 3, 3 seconds after being observed for the first time.
val data : LiveData<Int> = liveData {
    delay(3000)
    emit(3)
}


// a LiveData that fetches a `User` object based on a `userId` and refreshes it every 30 seconds
// as long as it is observed
val userId : LiveData<String> = ...
val user = userId.switchMap { id ->
    liveData {
      while(true) {
        // note that `while(true)` is fine because the `delay(30_000)` below will cooperate in
        // cancellation if LiveData is not actively observed anymore
        val data = api.fetch(id) // errors are ignored for brevity
        emit(data)
        delay(30_000)
      }
    }
}

// A retrying data fetcher with doubling back-off
val user = liveData {
    var backOffTime = 1_000
    var succeeded = false
    while(!succeeded) {
        try {
            emit(api.fetch(id))
            succeeded = true
        } catch(ioError : IOException) {
            delay(backOffTime)
            backOffTime *= minOf(backOffTime * 2, 60_000)
        }
    }
}

// a LiveData that tries to load the `User` from local cache first and then tries to fetch
// 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)
    }
}

// a LiveData that immediately receives a LiveData<User> from the database and yields it as a
// source but also tries to back-fill the database from the server
val user = liveData {
    val fromDb: LiveData<User> = roomDatabase.loadUser(id)
    emitSource(fromDb)
    val updated = api.fetch(id) // errors are ignored for brevity
    // Since we are using Room here, updating the database will update the `fromDb` LiveData
    // that was obtained above. See Room's documentation for more details.
    // https://developer.android.com/training/data-storage/room/accessing-data#query-observable
    roomDatabase.insert(updated)
}
```

| Parameters |
|---|---|
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/java/time/Duration.html timeout` | The timeout duration before cancelling the block if there are no active observers (`https://developer.android.com/reference/androidx/lifecycle/LiveData#hasActiveObservers()`. |
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html context` | The CoroutineContext to run the given block in. Defaults to `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-empty-coroutine-context/index.html` combined with `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-coroutine-dispatcher/immediate.html`. |
| `@https://developer.android.com/reference/androidx/annotation/NonNull SuspendFunction1<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/lifecycle/LiveDataScope<@https://developer.android.com/reference/androidx/annotation/NonNull T>, https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html> block` | The block to run when the `https://developer.android.com/reference/androidx/lifecycle/LiveData` has active observers. |