diff --git a/app/build.gradle b/app/build.gradle index 971e821084..cfc355a091 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -526,7 +526,7 @@ configurations.configureEach { } else if (details.requested.group == "androidx.lifecycle" && details.requested.name != "lifecycle-extensions") { //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n") - details.useVersion "2.7.0" + details.useVersion "2.8.1" } else if (details.requested.group == "org.apache.poi") { //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n") details.useVersion "3.17" @@ -547,11 +547,11 @@ dependencies { def startup_version = "1.2.0-alpha02" def annotation_version_experimental = "1.4.1" def core_version = "1.13.1" // 1.15.0-alpha01 - def appcompat_version = "1.6.1" // 1.7.0-rc01 + def appcompat_version = "1.7.0" def emoji_version = "1.4.0" // 1.5.0-alpha01 def flatbuffers_version = "2.0.0" def activity_version = " 1.9.0" - def fragment_version = "1.7.1" // 1.8.0 + def fragment_version = "1.8.0" def windows_version = "1.2.0" // 1.3.0-rc01 def webkit_version = "1.10.0" // 1.11.0/1.12.0-alpha02 def recyclerview_version = "1.3.2" // 1.4.0-alpha01 @@ -562,7 +562,7 @@ dependencies { def lbm_version = "1.1.0" def swiperefresh_version = "1.2.0-alpha01" def documentfile_version = "1.1.0-alpha01" - def lifecycle_version = "2.7.0" // 2.8.1 + def lifecycle_version = "2.8.1" def lifecycle_extensions_version = "2.2.0" def room_version = "2.4.3" // 2.5.2/2.6.1/2.7.0-alpha04 def sqlite_version = "2.4.0" // 2.5.0-alpha04 diff --git a/app/src/main/java/androidx/lifecycle/FlowLiveData.kt b/app/src/main/java/androidx/lifecycle/FlowLiveData.kt index 72d3ef74ee..51e541090c 100644 --- a/app/src/main/java/androidx/lifecycle/FlowLiveData.kt +++ b/app/src/main/java/androidx/lifecycle/FlowLiveData.kt @@ -18,22 +18,19 @@ package androidx.lifecycle -import android.annotation.SuppressLint import android.os.Build import androidx.annotation.RequiresApi import androidx.arch.core.executor.ArchTaskExecutor import java.time.Duration import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext -import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.conflate -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** @@ -84,7 +81,6 @@ public fun Flow.asLiveData( }.also { liveData -> val flow = this if (flow is StateFlow) { - @SuppressLint("RestrictedApi") if (ArchTaskExecutor.getInstance().isMainThread) { liveData.value = flow.value } else { @@ -104,7 +100,6 @@ public fun Flow.asLiveData( * BackPressure: the returned flow is conflated. There is no mechanism to suspend an emission by * LiveData due to a slow collector, so collector always gets the most recent value emitted. */ -@OptIn(DelicateCoroutinesApi::class) public fun LiveData.asFlow(): Flow = callbackFlow { val observer = Observer { trySend(it) @@ -113,8 +108,10 @@ public fun LiveData.asFlow(): Flow = callbackFlow { observeForever(observer) } - awaitClose { - GlobalScope.launch(Dispatchers.Main.immediate) { + try { + awaitCancellation() + } finally { + withContext(Dispatchers.Main.immediate + NonCancellable) { removeObserver(observer) } } diff --git a/app/src/main/java/androidx/lifecycle/LiveData.kt b/app/src/main/java/androidx/lifecycle/LiveData.kt new file mode 100644 index 0000000000..951350ba62 --- /dev/null +++ b/app/src/main/java/androidx/lifecycle/LiveData.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.lifecycle + +import androidx.annotation.MainThread + +/** + * Adds the given [onChanged] lambda as an observer within the lifespan of the given + * [owner] and returns a reference to observer. + * The events are dispatched on the main thread. If LiveData already has data + * set, it will be delivered to the onChanged. + * + * The observer will only receive events if the owner is in [Lifecycle.State.STARTED] + * or [Lifecycle.State.RESUMED] state (active). + * + * If the owner moves to the [Lifecycle.State.DESTROYED] state, the observer will + * automatically be removed. + * + * When data changes while the [owner] is not active, it will not receive any updates. + * If it becomes active again, it will receive the last available data automatically. + * + * LiveData keeps a strong reference to the observer and the owner as long as the + * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to + * the observer and the owner. + * + * If the given owner is already in [Lifecycle.State.DESTROYED] state, LiveData + * ignores the call. + */ +@Deprecated( + "This extension method is not required when using Kotlin 1.4. " + + "You should remove \"import androidx.lifecycle.observe\"" +) +@MainThread +public inline fun LiveData.observe( + owner: LifecycleOwner, + crossinline onChanged: (T) -> Unit +): Observer { + val wrappedObserver = Observer { t -> onChanged.invoke(t) } + observe(owner, wrappedObserver) + return wrappedObserver +} diff --git a/app/src/main/java/androidx/lifecycle/Transformations.kt b/app/src/main/java/androidx/lifecycle/Transformations.kt index e7bbf1f23d..b1e55d1f6f 100644 --- a/app/src/main/java/androidx/lifecycle/Transformations.kt +++ b/app/src/main/java/androidx/lifecycle/Transformations.kt @@ -49,9 +49,10 @@ import androidx.arch.core.util.Function fun LiveData.map( transform: (@JvmSuppressWildcards X) -> (@JvmSuppressWildcards Y) ): LiveData { - val result = MediatorLiveData() - if (isInitialized) { - result.value = transform(value as X) + val result = if (isInitialized) { + MediatorLiveData(transform(value as X)) + } else { + MediatorLiveData() } result.addSource(this) { x -> result.value = transform(x) } return result @@ -121,13 +122,16 @@ fun LiveData.map(mapFunction: Function): LiveData { fun LiveData.switchMap( transform: (@JvmSuppressWildcards X) -> (@JvmSuppressWildcards LiveData)? ): LiveData { - val result = MediatorLiveData() var liveData: LiveData? = null - if (isInitialized) { + val result = if (isInitialized) { val initialLiveData = transform(value as X) if (initialLiveData != null && initialLiveData.isInitialized) { - result.value = initialLiveData.value + MediatorLiveData(initialLiveData.value) + } else { + MediatorLiveData() } + } else { + MediatorLiveData() } result.addSource(this) { value: X -> val newLiveData = transform(value) @@ -183,11 +187,12 @@ fun LiveData.switchMap(switchMapFunction: Function>): L @MainThread @CheckResult fun LiveData.distinctUntilChanged(): LiveData { - val outputLiveData = MediatorLiveData() var firstTime = true - if (isInitialized) { - outputLiveData.value = value + val outputLiveData = if (isInitialized) { firstTime = false + MediatorLiveData(value) + } else { + MediatorLiveData() } outputLiveData.addSource(this) { value -> val previousValue = outputLiveData.value