Use disposable like pattern in SaveableStateRegistry
Relnote: SaveableStateRegistry's unregisterProvider was removed. Instead registerProvider() now returns SaveableStateRegistry.Entry object which you can use to unregister
Fixes: 178583739
Test: RememberSaveableTest, SaveableStateRegistryTest
Change-Id: Ic42741cecc67ce93cc097f01f7196110e2fff09d
diff --git a/compose/runtime/runtime-saveable/api/current.txt b/compose/runtime/runtime-saveable/api/current.txt
index bb252f1..0aedbbf 100644
--- a/compose/runtime/runtime-saveable/api/current.txt
+++ b/compose/runtime/runtime-saveable/api/current.txt
@@ -26,8 +26,11 @@
method public boolean canBeSaved(Object value);
method public Object? consumeRestored(String key);
method public java.util.Map<java.lang.String,java.util.List<java.lang.Object>> performSave();
- method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
- method public void unregisterProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public androidx.compose.runtime.saveable.SaveableStateRegistry.Entry registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ }
+
+ public static interface SaveableStateRegistry.Entry {
+ method public void unregister();
}
public final class SaveableStateRegistryKt {
diff --git a/compose/runtime/runtime-saveable/api/public_plus_experimental_current.txt b/compose/runtime/runtime-saveable/api/public_plus_experimental_current.txt
index bb252f1..0aedbbf 100644
--- a/compose/runtime/runtime-saveable/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime-saveable/api/public_plus_experimental_current.txt
@@ -26,8 +26,11 @@
method public boolean canBeSaved(Object value);
method public Object? consumeRestored(String key);
method public java.util.Map<java.lang.String,java.util.List<java.lang.Object>> performSave();
- method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
- method public void unregisterProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public androidx.compose.runtime.saveable.SaveableStateRegistry.Entry registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ }
+
+ public static interface SaveableStateRegistry.Entry {
+ method public void unregister();
}
public final class SaveableStateRegistryKt {
diff --git a/compose/runtime/runtime-saveable/api/restricted_current.txt b/compose/runtime/runtime-saveable/api/restricted_current.txt
index bb252f1..0aedbbf 100644
--- a/compose/runtime/runtime-saveable/api/restricted_current.txt
+++ b/compose/runtime/runtime-saveable/api/restricted_current.txt
@@ -26,8 +26,11 @@
method public boolean canBeSaved(Object value);
method public Object? consumeRestored(String key);
method public java.util.Map<java.lang.String,java.util.List<java.lang.Object>> performSave();
- method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
- method public void unregisterProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public androidx.compose.runtime.saveable.SaveableStateRegistry.Entry registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ }
+
+ public static interface SaveableStateRegistry.Entry {
+ method public void unregister();
}
public final class SaveableStateRegistryKt {
diff --git a/compose/runtime/runtime-saveable/src/androidAndroidTest/kotlin/androidx/compose/runtime/saveable/RememberSaveableTest.kt b/compose/runtime/runtime-saveable/src/androidAndroidTest/kotlin/androidx/compose/runtime/saveable/RememberSaveableTest.kt
index 706b0e3..25bcd69 100644
--- a/compose/runtime/runtime-saveable/src/androidAndroidTest/kotlin/androidx/compose/runtime/saveable/RememberSaveableTest.kt
+++ b/compose/runtime/runtime-saveable/src/androidAndroidTest/kotlin/androidx/compose/runtime/saveable/RememberSaveableTest.kt
@@ -120,9 +120,12 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
provider = valueProvider
- super.registerProvider(key, valueProvider)
+ return super.registerProvider(key, valueProvider)
}
}
}
@@ -145,9 +148,12 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
provider = valueProvider
- super.registerProvider(key, valueProvider)
+ return super.registerProvider(key, valueProvider)
}
}
}
@@ -167,9 +173,17 @@
var registryFactory by mutableStateOf<(SaveableStateRegistry) -> SaveableStateRegistry>(
value = {
object : DelegateRegistry(it) {
- override fun unregisterProvider(key: String, valueProvider: () -> Any?) {
- unregisterCalledForKey = key
- super.unregisterProvider(key, valueProvider)
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
+ val entry = super.registerProvider(key, valueProvider)
+ return object : SaveableStateRegistry.Entry {
+ override fun unregister() {
+ unregisterCalledForKey = key
+ entry.unregister()
+ }
+ }
}
}
}
@@ -191,12 +205,16 @@
rule.runOnUiThread {
registryFactory = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
- super.registerProvider(key, valueProvider)
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
+ val result = super.registerProvider(key, valueProvider)
// asserts that we unregistered from the previous registry and then
// registered with the same key
assertThat(key).isEqualTo(unregisterCalledForKey)
registerCalled = true
+ return result
}
}
}
@@ -215,15 +233,19 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
- super.registerProvider(key, valueProvider)
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
+ val entry = super.registerProvider(key, valueProvider)
registeredKeys.add(key)
registerCalled++
- }
-
- override fun unregisterProvider(key: String, valueProvider: () -> Any?) {
- super.unregisterProvider(key, valueProvider)
- registeredKeys.remove(key)
+ return object : SaveableStateRegistry.Entry {
+ override fun unregister() {
+ registeredKeys.remove(key)
+ entry.unregister()
+ }
+ }
}
}
}
@@ -280,9 +302,17 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun unregisterProvider(key: String, valueProvider: () -> Any?) {
- onUnregisterCalled = true
- super.unregisterProvider(key, valueProvider)
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
+ val entry = super.registerProvider(key, valueProvider)
+ return object : SaveableStateRegistry.Entry {
+ override fun unregister() {
+ onUnregisterCalled = true
+ entry.unregister()
+ }
+ }
}
}
}
@@ -310,9 +340,12 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
actualKey = key
- super.registerProvider(key, valueProvider)
+ return super.registerProvider(key, valueProvider)
}
}
}
@@ -332,9 +365,12 @@
WrapRegistry(
wrap = {
object : DelegateRegistry(it) {
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ override fun registerProvider(
+ key: String,
+ valueProvider: () -> Any?
+ ): SaveableStateRegistry.Entry {
actualKey = key
- super.registerProvider(key, valueProvider)
+ return super.registerProvider(key, valueProvider)
}
}
}
diff --git a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
index 22f3585..fa0fe95 100644
--- a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
+++ b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
@@ -89,9 +89,9 @@
with(saverHolder.value) { SaverScope { registry.canBeSaved(it) }.save(value) }
}
registry.requireCanBeSaved(valueProvider())
- registry.registerProvider(finalKey, valueProvider)
+ val entry = registry.registerProvider(finalKey, valueProvider)
onDispose {
- registry.unregisterProvider(finalKey, valueProvider)
+ entry.unregister()
}
}
}
diff --git a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/SaveableStateRegistry.kt b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/SaveableStateRegistry.kt
index 4a971f5..4821841 100644
--- a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/SaveableStateRegistry.kt
+++ b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/SaveableStateRegistry.kt
@@ -16,6 +16,7 @@
package androidx.compose.runtime.saveable
+import androidx.compose.runtime.saveable.SaveableStateRegistry.Entry
import androidx.compose.runtime.staticAmbientOf
/**
@@ -44,16 +45,9 @@
* @param key Key to use for storing the value
* @param valueProvider Provides the current value, to be executed when [performSave]
* will be triggered to collect all the registered values
+ * @return the registry entry which you can use to unregister the provider
*/
- fun registerProvider(key: String, valueProvider: () -> Any?)
-
- /**
- * Unregisters the value provider previously registered via [registerProvider].
- *
- * @param key Key of the value which shouldn't be saved anymore
- * @param valueProvider The provider previously passed to [registerProvider]
- */
- fun unregisterProvider(key: String, valueProvider: () -> Any?)
+ fun registerProvider(key: String, valueProvider: () -> Any?): Entry
/**
* Returns true if the value can be saved using this Registry.
@@ -68,6 +62,16 @@
* a list of values for each key as it is allowed to have multiple providers for the same key.
*/
fun performSave(): Map<String, List<Any?>>
+
+ /**
+ * The registry entry which you get when you use [registerProvider].
+ */
+ interface Entry {
+ /**
+ * Unregister previously registered entry.
+ */
+ fun unregister()
+ }
}
/**
@@ -109,21 +113,19 @@
}
}
- override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ override fun registerProvider(key: String, valueProvider: () -> Any?): Entry {
require(key.isNotBlank()) { "Registered key is empty or blank" }
@Suppress("UNCHECKED_CAST")
valueProviders.getOrPut(key) { mutableListOf() }.add(valueProvider)
- }
-
- override fun unregisterProvider(key: String, valueProvider: () -> Any?) {
- val list = valueProviders.remove(key)
- val found = list?.remove(valueProvider)
- require(found == true) {
- "The given key $key , valueProvider pair wasn't previously registered"
- }
- if (list.isNotEmpty()) {
- // if there are other providers for this key return list back to the map
- valueProviders[key] = list
+ return object : Entry {
+ override fun unregister() {
+ val list = valueProviders.remove(key)
+ list?.remove(valueProvider)
+ if (list != null && list.isNotEmpty()) {
+ // if there are other providers for this key return list back to the map
+ valueProviders[key] = list
+ }
+ }
}
}
diff --git a/compose/runtime/runtime-saveable/src/test/java/androidx/compose/runtime/saveable/SaveableStateRegistryTest.kt b/compose/runtime/runtime-saveable/src/test/java/androidx/compose/runtime/saveable/SaveableStateRegistryTest.kt
index bf3ec29..1dbda70 100644
--- a/compose/runtime/runtime-saveable/src/test/java/androidx/compose/runtime/saveable/SaveableStateRegistryTest.kt
+++ b/compose/runtime/runtime-saveable/src/test/java/androidx/compose/runtime/saveable/SaveableStateRegistryTest.kt
@@ -40,8 +40,8 @@
val registry = createRegistry()
val provider = { 10 }
- registry.registerProvider("key", provider)
- registry.unregisterProvider("key", provider)
+ val entry = registry.registerProvider("key", provider)
+ entry.unregister()
registry.performSave().apply {
assertThat(containsKey("key")).isFalse()
@@ -53,8 +53,8 @@
val registry = createRegistry()
val provider1 = { "value1" }
- registry.registerProvider("key", provider1)
- registry.unregisterProvider("key", provider1)
+ val entry = registry.registerProvider("key", provider1)
+ entry.unregister()
registry.registerProvider("key") { "value2" }
registry.performSave().apply {
@@ -68,10 +68,10 @@
registry.registerProvider("key1") { 100L }
val provider2 = { 100 }
- registry.registerProvider("key2", provider2)
+ val entry = registry.registerProvider("key2", provider2)
registry.registerProvider("key3") { "value" }
registry.registerProvider("key4") { listOf("item") }
- registry.unregisterProvider("key2", provider2)
+ entry.unregister()
registry.performSave().apply {
assertThat(get("key1")).isEqualTo(listOf(100L))
@@ -180,10 +180,9 @@
val registry = createRegistry()
registry.registerProvider("key") { 1L }
- val provider2 = { 2 }
- registry.registerProvider("key", provider2)
- registry.registerProvider("key") { 3 }
- registry.unregisterProvider("key", provider2)
+ val entry = registry.registerProvider("key") { 2L }
+ registry.registerProvider("key") { 3L }
+ entry.unregister()
val restoredRegistry = createRegistry(registry.performSave())
assertThat(restoredRegistry.consumeRestored("key")).isEqualTo(1L)
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/StateRestorationTester.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/StateRestorationTester.kt
index cbbb360..90e1c1a 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/StateRestorationTester.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/StateRestorationTester.kt
@@ -116,9 +116,6 @@
override fun registerProvider(key: String, valueProvider: () -> Any?) =
currentRegistry.registerProvider(key, valueProvider)
- override fun unregisterProvider(key: String, valueProvider: () -> Any?) =
- currentRegistry.unregisterProvider(key, valueProvider)
-
override fun canBeSaved(value: Any) = currentRegistry.canBeSaved(value)
override fun performSave() = currentRegistry.performSave()