Status Update
Comments
il...@google.com <il...@google.com>
il...@google.com <il...@google.com> #2
Branch: androidx-master-dev
commit c60f33e229e31ab328ef6b59dab63b264954831c
Author: Alexandre Elias <aelias@google.com>
Date: Fri Jul 10 16:23:09 2020
Semantics no-op cleanups
Partly in response to lmr's broad code review, I did a pass of
superficial API/implementation cleanup. The main changes are:
- I changed each Boolean SemanticsProperty where false is equivalent to
not being present to take "Unit" instead. This is conceptually
clearer: it avoids questions like "can I cancel out a semantics from a
merged child by setting it to false?" Because "property = Unit" looks
weird, I also changed the style of these to "property()".
- I moved the Semantics id generator closer to where it's used, in
SemanticsModifierCore. I made it internal and an AtomicInt.
(Note that integer ids are heavily used in the Android
AccessibilityNodeInfo APIs so I can't simply remove them entirely.)
- I deleted dead code. Some examples include SemanticsHintOverrides,
a public API not connected to anything, and SemanticsPropertyKey
merge() open method which is never called. (In both cases I have
a different plan in mind for accessibility.)
Fixes: 145951226
Fixes: 145955412
Test: existing tests
Relnote: "Single-value semantics properties now use a calling style.
For example, 'semantics { hidden = true }' is now written as:
'semantics { hidden() }'."
Change-Id: Ic1afd12ea22c926babc9662f1804d80b33aa0cfc
M ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
M ui/ui-core/api/0.1.0-dev15.txt
M ui/ui-core/api/current.txt
M ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-core/api/public_plus_experimental_current.txt
M ui/ui-core/api/restricted_0.1.0-dev15.txt
M ui/ui-core/api/restricted_current.txt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/VectorTest.kt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/semantics/SemanticsTests.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidActuals.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidPopup.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/Expect.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsConfiguration.kt
D ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsHintOverrides.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsOwner.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/semantics/SemanticsProperties.kt
M ui/ui-foundation/api/0.1.0-dev15.txt
M ui/ui-foundation/api/current.txt
M ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-foundation/api/public_plus_experimental_current.txt
M ui/ui-foundation/api/restricted_0.1.0-dev15.txt
M ui/ui-foundation/api/restricted_current.txt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Dialog.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/semantics/FoundationSemanticsProperties.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CardTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SurfaceTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
M ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
M ui/ui-material/src/main/java/androidx/ui/material/TextFieldImpl.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/AssertsTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/CallSemanticsActionTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ErrorMessagesTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/PrintToStringTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/TextActionsTest.kt
M ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
M ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
M ui/ui-text/api/0.1.0-dev15.txt
M ui/ui-text/api/current.txt
M ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-text/api/public_plus_experimental_current.txt
M ui/ui-text/api/restricted_0.1.0-dev15.txt
M ui/ui-text/api/restricted_current.txt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/CoreTextField.kt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/TextSemanticsProperties.kt
va...@google.com <va...@google.com> #3
For the version added to Lifecycle, I wonder if matching the signature of rememberSaveable
would be good for consistency:
var saved by savedStateHandle.saveable("key") { mutableStateOf("initialState") }
That would also allow saving a state holder which may not want to be wrapped in a MutableState
which exposes a custom Saver
(like rememberSaveable
allows):
val myStateHolder = savedStateHandle.saveable("key", saver = MyStateHolder.Saver) { MyStateHolder() }
That could look something like
fun <T : Any> SavedStateHandle.saveable(
key: String,
saver: Saver<T, out Any> = autoSaver(),
init: () -> T,
): T {
@Suppress("UNCHECKED_CAST")
saver as Saver<T, Any>
// value is restored using the SavedStateHandle or created via [init] lambda
val value = get<Bundle?>(key)?.get("value")?.let(saver::restore) ?: init()
// Hook up saving the state to the SavedStateHandle
setSavedStateProvider(key) {
bundleOf("value" to with(saver) { SaverScope { true }.save(value) })
}
return value
}
il...@google.com <il...@google.com>
al...@gmail.com <al...@gmail.com> #4
Are these states supposed to survive user completion of the activity? I.e. are these saved states recoverable when killing the app and starting it again?
Compared to SavedInstanceState (which do not according to:
va...@google.com <va...@google.com> #5
No, the states would follow the same lifetime as other state stored in SavedStateHandle
, which follows the same rules as Saved instance state
from that table (serialized to disk, survives process death, only supports simple, small objects).
The goal isn't to all state to survive user completion of the activity, but to allow using the same Saver
abstraction for rememberSaveable
and SavedStateHandle
.
ap...@google.com <ap...@google.com> #6
Branch: androidx-main
commit 0d614efac51fd8308d3a8d1a4ac3a86fd89caa03
Author: Jeremy Woods <jbwoods@google.com>
Date: Tue Mar 01 17:01:49 2022
Add experimental SavedStateHandle Saver support
Added an experimental API at the lifecycle level to provide a temporary
hook for SavedStateHandle into compose Saver while we work on a longer
term integration plan.
RelNote: "The `lifecycle-viewmodel-compose` module now provides
`SavedStateHandleSaver`, an experimental API that ensures values in a
`SavedStateHandle` are integrated correctly with the same saved instance
state that `rememberSaveable` uses."
Test: N/A
Bug: 195689777
Change-Id: Ia88b79c56a5f82263ddaf436777dfc1c4ab73704
M lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
M lifecycle/lifecycle-viewmodel-savedstate/src/main/java/androidx/lifecycle/SavedStateHandle.kt
M lifecycle/lifecycle-viewmodel-compose/api/current.txt
M lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-viewmodel-compose/build.gradle
A lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/SavedStateHandleSaveableApi.kt
A lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/SavedStateHandleSaverTest.kt
A lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/SavedStateHandleSaver.kt
jb...@google.com <jb...@google.com> #7
This has been added internally and will be in the Lifecycle 2.5.0-alpha05
release.
Description
Compose provides
rememberSaveable
, along with accompanying tools likeSaver
andSaveableStateRegistry
as its mechanisms for storing saved instance state. Currently, there isn't a provided interoperability layer between these tools andSavedStateHandle
.If
SavedStateHandle
isn't used in theViewModel
, state that is hoisted from@Composable
s toViewModel
s won't be stored to saved instance state. This might either cause bugs due to state loss upon process death, or act as a barrier to hoisting state sufficiently if it seems likerememberSaveable
has to be used to remember state across process recreation.The proposal is to provide the necessary hooks for
SavedStateHandle
withSaver
so that any state holder that is being saved viarememberSaveable
could also be saved withSavedStateHandle
.