yousef shaaban
05/04/2025, 4:09 PMkrzysztof
05/04/2025, 7:58 PMNavigation destination that matches request (…) cannot be found in the navigation graph
. I found out that uri decoding the value in overridden serializeAsValue
method makes it work, but I cannot find it anywhere mentioned it documentation. Is this the right approach or is there something I’m missing?Colton Idle
05/04/2025, 8:08 PM@Composable
fun InstrumentsList() {
var instruments by remember { mutableStateOf<List<Instrument>>(listOf()) }
LaunchedEffect(Unit) {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
instruments = supabase.from("instruments")
.select().decodeList<Instrument>()
}
}
Could you just move the work from the LaunchedEffect to the remember {}.block?eneim
05/05/2025, 12:20 PMremoveAllViews()
when childCount
is <= 0
in the else
flow. In stead, should the removeAllViews()
is called right before creating a new AndroidComposeView
instance and in the same block:
// Suggestion:
val composeView = if (childCount > 0) { getChildAt(0) as? AndroidComposeView } else { null } ?: /* at this point we know the parent doesn't contain any AndroidComposeView, regardless of its childCount, so we have to ensure it is empty and then add a new AndroidComposeView to it */ run {
removeAllViews()
// Create a new AndroidComposeView and "also" add it to "this".
}
From the code, it seems that, if childCount > 0
but the first child is not an AndroidComposeView
, the parent doesn't clear it before adding the newly created one.
Also, (AFAIK) even when childCount <= 0
, calling removeAllViews()
will cause a layout traversal so doing it seems to be unnecessary.eneim
05/05/2025, 12:53 PMWrappedComposition
will be reused under some conditions to optimize the performance (e.g., using in a PoolingContainer like RecyclerView). However, in such case, it seems that WrapperComposition.addedToLifecycle
field is never updated after the first set to non-null call.
I guess the class assumes that the containing AndroidComposeView is added to at most one lifecycle? But in the case of RecyclerView, we can specify a RecycledViewPool at the Activity's scope, whiles RecyclerView instances using that Pool are in Fragments of that Activity --> an AndroidComposeView could be (re)used across different Lifecycle (i.e. different Fragments).
Combine with the code in the 2nd screenshot (onStateChanged), I can see that: if a AndroidComposeView is used to a Fragment A, then re-used-without-decomposing in a Fragment B, if the destruction of Fragment A happens after the creation of Fragment B, then the WrappedComposition will be disposed and the UI is gone.
JFYI, the Epoxy library utilizes this Activity-bound Pool by default & I could reproduce the UI-be-gone issue above (not as high confidence, but still). I assume any implementation using a similar Pool has this issue, not Epoxy-specific issue.
I think a code change like below can address it:
// WrappedComposition.setContent, line 118.
val lifecycle = it.lifecycleOwner.lifecycle
lastContent = content
if (addedToLifecycle != lifecycle) {
addedToLifecycle?.removeObserver(this@WrappedComposition) // Added to a new Lifecycle, so it must detach from the old one, if any.
addedToLifecycle = lifecycle
// this will call ON_CREATE synchronously if we already created
lifecycle.addObserver(this)
} // else ...
ankur samarya
05/05/2025, 12:53 PMBar
is not recomposing with the new lambda instance?
In this example code, I am creating a new instance of onBarClick
every time the state changes.
Since it's a new instance, the Bar
should recompose as well — but it's not.
I've disabled strong skipping using enableStrongSkippingMode = false
.
@Composable
fun Foo() {
val state = remember {
mutableIntStateOf(1)
}
val onBarClick = {}
Log.d("logs", "Foo Recomposition ${onBarClick}" )
Column {
Text(text = "Value ${state.value}")
Bar(onBarClick = onBarClick)
Button(onClick = { state.value++ }) {
Text(text = "Increment")
}
}
}
@Composable
fun Bar(onBarClick: () -> Unit) {
Log.d("logs", "Bar Recomposition" )
Button(onClick = onBarClick) {
Text(text = "Dummy Button")
}
}
ThanksMadhur
05/05/2025, 1:14 PMComposeUIViewController
from androidx.compose.ui.window
but I get error saying class not found. I can confirm it not being present at External Dependencies > androidx.compose.ui.window
.
However, I can see it working in the Confetti sample with the same versions. When I try to locate ComposeUIViewController
in this project it shows the path as .kotlin > metadata > kotlinTransformedMetadataLibraries > org.jetbrains.compose.ui-ui-1.7.3-uikitMain-bkbtDw.klib > default > linkdata > package_androidx.compose.ui.window
?
Can someone help me on how is the linking for ComposeUIViewController happening in Confetti example?Arne Vanstraeseele
05/05/2025, 2:08 PMStefan Oltmann
05/05/2025, 3:29 PMval imageBitmap = makeImageFromByteArray(bytes).toComposeImageBitmap()
The suggestion is to do this instead:
val image = makeImageFromByteArray(bytes)
val imageBitmap = image.use {
it.toComposeImageBitmap()
}
The reason behind that is that the SKIA image will not be closed after the copy process and the native resources not be freed up... That may be one of the issues for memory issues I experienced on iOS.
I don't find anything how to properly use toComposeImageBitmap()
Is is true that the SKIA image behind will not be freed immediately after a method like this completed?
fun createImage(bytes: ByteArray) = makeImageFromByteArray(bytes).toComposeImageBitmap()
Is there a way/need to dispose()/close() the ImageBitmap after the Composable disposes?Howaye
05/05/2025, 9:39 PMCompositionLocal
to pass composable lambda to a child composable? Something like below.
val LocalComposable = compositionLocalOf<@Composable (Modifier) -> Unit> { { Box {} } }
@Composable
fun DescendantDeepInHiearchy() {
LocalComposable.current
}
I did see in the Alternatives to Consider section about IOC, mentioning composable lambdas benefiting from IOC. I didn't find whether it would be a good or bad idea to to use composable lambdas in CompositionLocal
Dylan Sale
05/05/2025, 11:42 PMUsman
05/06/2025, 12:45 AMAmrJyniat
05/06/2025, 10:21 AMAvinash
05/06/2025, 10:25 AMGabriel Stefan
05/06/2025, 10:40 AM@Composable
fun MyComposable(input: Type?) {
if (input != null) {
XComposable(input)
} else {
YComposable()
}
}
vs
@Composable
fun MyComposable(input: Type?) {
input?.let {
XComposable(input)
} ?: YComposable()
}
My intuition is telling me that the first one is more idiomatic + it seems easier to understand at a glance but I can’t seem to find any references for that (so if you know of any I’d appreciate linking them)Peter
05/06/2025, 11:40 AMTextField
not focusable, but still keep it clickable?Usman
05/06/2025, 12:37 PMTimothy Joseph
05/06/2025, 1:50 PMval inNightMode = LocalNightMode.current
val context = LocalContext.current
val mContext = remember (inNightMode){ context.withForcedNightMode(inNightMode) }
val ctxThemeWrapper = remember(mContext) {
ContextThemeWrapper(mContext,R.style.Theme_PROlauncher)
}
AndroidView(factory = { ctx ->
TextView(ctxThemeWrapper)
})
,...... so that's fixed too The app supports edge to edge, but I added some margin to the bottom of the composables to make it seem as if it's above the navigation bar and Now I have to set a translucent navigation Bar and change the navigation bar icon to based on the theme mode since that was part of the attributes in the themes.xml, and anytime I set the custom theme mode to light and toggle the nav bar icons based on this, instead of starting at the edge of the screen, the margins I added start from the top of the nav bar and also the transluscent bg becomes completely white
val insetsController = WindowCompat.getInsetsController(window, window.decorView)
insetsController.isAppearanceLightNavigationBars = isLightTheme
the full method
@Composable
fun ApplyEdgeToEdge(isLightTheme: Boolean) {
val view = LocalView.current val activity = view.context as Activity
SideEffect {
val window = activity.window
// Ensure edge-to-edge layout
WindowCompat.setDecorFitsSystemWindows(window, false)
// Transparent system bars
window.navigationBarColor = Color.Transparent.toArgb()
// Disable nav bar contrast (API 29+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
// Optional (legacy translucent fallback)
@Suppress("DEPRECATION")
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
// Control icons
val insetsController = WindowCompat.getInsetsController(window, window.decorView)
insetsController.isAppearanceLightNavigationBars = isLightTheme
}
}
is there a way I could fix this???mattinger
05/06/2025, 3:48 PMArsildo Murati
05/06/2025, 5:24 PMCedrick Cooke
05/06/2025, 11:46 PMCache-Control
header server-side, but client-side still ends up revalidating the request for each string and receiving a lot of 304
responses sequentially.mattinger
05/07/2025, 6:51 PMwithText
do not work because we're not extending TextView. I can write explicit matchers on properties of that wrapper, but i'd like to be able to use the root view and execute any composed based matcher on that. Anyone have any idea if this is possible?
Something like:
onView(
allOf(
withId(R.id.button),
withComposeText(buttonText)
)
)
And someone internally look at the compose tree for that view and execute the text assertion there.Jonathan
05/07/2025, 9:06 PMBackHandler
?Lukas Anda
05/07/2025, 9:47 PMLukasz Kalnik
05/08/2025, 9:40 AMoverride fun onCreate(...) {
setContent {
uiState by viewModel.uiState.collectAsStateWithLifecycle()
MyTheme {
MyScreen(uiState)
(uiState.overlayState as? ScannedItemOvelayState)?.let { scannedItemOverlayState ->
MyOverlay(scannedItemOverlayState)
}
}
}
}
The flakiness is that MyOverlay
is sometimes not hidden even though showOverlay
is null.
However, when I wrap those both composables in a Box
, MyOverlay
is hidden reliably every time.Nitesh Singh
05/08/2025, 10:15 AMMarkRS
05/08/2025, 1:08 PMOmico
05/09/2025, 1:10 AM@Immutable
data class GalleryUiState(
val galleryImagePagingData: Flow<PagingData<GalleryImage>> = emptyFlow(),
val eventSink: (GalleryUiEvent) -> Unit = {},
) {
companion object {
val Empty: GalleryUiState = GalleryUiState()
}
}
Currently, I have to use Flow<PagingData<GalleryImage>>
inside of the UiState, but I don't think this is a good practice. If I use PagingData<GalleryImage>
instead, which cause me unable to use collectAsLazyPagingItems()
in the Composable function.
Full project here https://github.com/Omico/picsum
I saw Chris circumventing this by using Circuit, but it seems like a better design pattern is needed if we want to achieve it without using Circuit. https://github.com/chrisbanes/tivi/blob/a0c62c2c763c83e3a0ecf79b283224374bb06c4a/u[…]ommonMain/kotlin/app/tivi/home/popular/PopularShowsPresenter.ktmohamed rejeb
05/09/2025, 9:01 AMJonathan
05/09/2025, 1:14 PMCanvas {}
to draw a custom graph and I’d like to report the trig values (sin
, cos
, tan
, theta
) at which the graph was last interacted to calling code. My concern is invoking the callback to often even when the angle hasn’t changed (I do some rounding so tiny changes won’t be reflected). Is this a better use for custom state class to hold the values?