Status Update
Comments
ma...@google.com <ma...@google.com>
as...@google.com <as...@google.com> #2
Does the program work without the compiler switch. That is, is `"-P", "plugin:androidx.compose.compiler.plugins.kotlin:experimentalStrongSkipping=true",` required to reproduce or is just changing the runtime enough?
ke...@gmail.com <ke...@gmail.com> #3
Sorry for that, I will try to extract an example when I'm free.
as...@google.com <as...@google.com> #4
I have find a sample code to reproduce that
setContent {
val dialogState = remember { DialogState() }
dialogState.Intercept()
LaunchedEffect(Unit) {
delay(1000)
dialogState.bgWork {
delay(5000)
}
dialogState.showSelectActions {
onSelect("a") {
}
onSelect("b") {
}
}
}
}
You can find implementation of DialogState
here
as...@google.com <as...@google.com> #5
Let me sort it out
The first crash
Reproduce: navigate to a gallery and navigate back
The reason is we have some code assume the forget order of RememberObserver(DisposableEffect), and 52835066c9044647a65dfb566f03131aab46e793
changed the order. Seems this is a intended behaviour.
I will fix it from my side. My bad
The second crash
Reproduce: #4 comment
StackTrace:
We got a wrong object from SlotTable during recompose
as...@google.com <as...@google.com> #6
And interestingly, if we insert delay(1000) between two dialog suspend usage
dialogState.bgWork {
delay(5000)
}
delay(1000)
dialogState.showSelectActions {
onSelect("a") {
}
onSelect("b") {
}
}
It will not crash
ap...@google.com <ap...@google.com> #7
As for the order of `onForgotten`, it may be you are seeing and issue that I fixed in a subsequent version as this, for the snapshot builds, was broken for a few weeks when using the non-skipping group optimization even indirectly.
ap...@google.com <ap...@google.com> #8
al...@google.com <al...@google.com> #9
I tried cutting down the example myself and was not able to reproduce this.
The primary dependency chagnes I made were:
compose-material3 = { module = "androidx.compose.material3:material3", version = "1.3.0-SNAPSHOT" }
compose-foundation = { module = "androidx.compose.foundation:foundation-android", version = "1.7.0-SNAPSHOT" }
I only included the part of the Dialog.kt that was needed by the above,
class DialogState {
var content: (@Composable () -> Unit)? by mutableStateOf(null)
@Composable
fun Intercept() = content?.invoke()
fun dismiss() {
content = null
}
suspend inline fun <R> dialog(crossinline block: @Composable (CancellableContinuation<R>) -> Unit) = suspendCancellableCoroutine<R> { cont ->
cont.invokeOnCancellation { dismiss() }
val realContinuation = object : CancellableContinuation<R> by cont {
override fun resumeWith(result: Result<R>) {
dismiss()
cont.resumeWith(result)
}
}
content = { block(realContinuation) }
}
suspend inline fun showSelectActions(
title: String? = null,
builder: ActionScope.() -> Unit,
) {
val (items, actions) = buildList { builder(ActionScope { action, that -> add(action to that) }) }.unzip()
val selected = showSelectItem(items, title)
actions[selected].invoke()
}
suspend fun showSelectItem(
items: List<String>,
title: String?,
respectDefaultWidth: Boolean = true,
): Int = showNoButton(respectDefaultWidth) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
if (title != null) {
Text(
text = title,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 8.dp),
style = MaterialTheme.typography.headlineSmall,
)
}
LazyColumn {
itemsIndexed(items) { index, text ->
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.tertiary) {
Text(
text = text,
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 16.dp),
style = MaterialTheme.typography.titleMedium,
)
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
suspend fun <R> showNoButton(respectDefaultWidth: Boolean = true, block: @Composable DismissDialogScope<R>.() -> Unit): R {
return dialog { cont ->
val impl = remember(cont) {
DismissDialogScope<R> {
cont.resume(it)
}
}
BasicAlertDialog(
onDismissRequest = { cont.cancel() },
properties = DialogProperties(usePlatformDefaultWidth = respectDefaultWidth),
content = {
Surface(
modifier = with(Modifier) { if (!respectDefaultWidth) defaultMinSize(280.dp) else width(280.dp) },
shape = AlertDialogDefaults.shape,
color = AlertDialogDefaults.containerColor,
tonalElevation = AlertDialogDefaults.TonalElevation,
content = { block(impl) },
)
},
)
}
}
}
fun interface ActionScope {
fun onSelect(action: String, that: suspend () -> Unit)
}
fun interface DismissDialogScope<R> {
fun dismissWith(value: R)
}
This shows the "Please wait" and then selection between "a" and "b" as I expected.
as...@google.com <as...@google.com> #10
This requires compose compiler 1.5.11-dev-k2.0.0-Beta4-21f5e479a96
I will upload a sample project soon
Description
Jetpack Compose version: 1.4.0-alpha03
Jetpack Compose component(s) used: LazyColumn
Android Studio Build: Android Studio Electric Eel | 2022.1.1 RC 1
Kotlin version: 1.7.20
Originally, I asked this question on #compose slack channel but I was asked to report it here.
"Hi. I'm currently using Compose 1.4.0-alpha03 and I'm experiencing a weird behavior where updating bottom padding of
PaddingValue
which is then passed toLazyColumn(contentPadding = ...)
doesn't actually use the new padding inside of therememberLazyListMeasurePolicy
. The bottom padding is updated with the keyboard height everytime it appears/disappears. I'm placing two breakpoints 1. Inside of the internal funLazyList(...)
function onstate.placementAnimator = placementAnimator
line. 2. Inside of the private funrememberLazyListMeasurePolicy()
function oncheckScrollableContainerConstraints()
line. Then I'm clicking a textfield to make the keyboard appear. Once the first breakpoint is hit I first check that the bottom padding is the value I'm expecting to see (~300dp) then I place a new breakpoint inside ofPaddingValuesImpl.equals()
method. Then I resume the app,PaddingValuesImpl.equals()
is getting called a couple of times but it's called not from the place I'm expecting it to get called from. I'm expecting a call fromremember<LazyLayoutMeasureScope.(Constraints) -> MeasureResult>() { ... }
line which is inrememberLazyListMeasurePolicy()
method but it never gets called from that method. Then the second breakpoint which is oncheckScrollableContainerConstraints()
line is getting hit and when I check thecontentPadding
I'm seeing the old value (24dp). So I'm assuming that theremember<LazyLayoutMeasureScope.(Constraints) -> MeasureResult>() { ... }
doesn't work for some reason in this situation so the lambda is not re-remebered in other words it's the previous lambda that captured the previouscontentPadding
. I would really like to see what's going on insideremember<LazyLayoutMeasureScope.(Constraints) -> MeasureResult>() { ... }
but I can't place a breakpoint there because it tells me to download the source code and when I click download it can't find it. I tried installing the compose-runtime dependency but it still won't show me the source code of thatremember<LazyLayoutMeasureScope.(Constraints) -> MeasureResult>() { ... }
function. This feels like a bug in that one remember function. However I also tried to create a new project and copy some of the code to try and reproduce the issue but it works just fine there (same compose version). So I'm kinda lost now. I'm not sure I should report this on the issue tracker because I have no MRE and it also works in a new test project but doesn't work in the main project. The app I'm developing is open-source so I can provide the whole project if needed."STR:
If you do the steps described above (the one with breakpoints) you will see the bug. I'm also attaching a video where I'm doing those steps.
As I have already said above I tried to create a MRE in a new project but was surprised to see that it works there flawlessly. Also I have multiple places in this project where I'm using the same method to set the bottom padding of the LazyColumn when the keyboard shows up and it works in some of those places.