I'm a bit stuck with coroutines here. I have a Boo...
# compose-android
n
I'm a bit stuck with coroutines here. I have a Boolean
isBeingProcessed
that triggers a loading animation when the wallpaper is being set, and then stops on completion. This Boolean is only ever taken into account if I add a short delay at the start of the coroutine. The problem is that the delay also freezes my loading animation. How could I do this correctly? 🧵
Copy code
"Set as scrolling wallpaper" -> {  
                            isBeingProcessed = true
                            scope.launch {
                                wallpaperManager.setBitmap(
                                    bmp, null, true, flags
                                )
                            }.invokeOnCompletion {
                                isBeingProcessed = false
                                isSheetOpen = false
                                Toast.makeText(
                                    context,
                                    "Wallpaper set successfully",
                                    Toast.LENGTH_SHORT
                                ).show()
                            }
                        }
s
Is
isBeingProcessed
a MutableState? Probably worth showing a bit more code around this.
n
Yes it is:
Copy code
var isBeingProcessed by rememberSaveable { mutableStateOf(false) }
and
Copy code
if (isBeingProcessed) {
    Dialog(onDismissRequest = {}) {
        LoadingAnimation()
    }
}
Worth noting that all works well when I use this option:
Copy code
"Set as cropped wallpaper" ->
    (context as? ComponentActivity)?.let { activity ->
        scope.launch {
            isBeingProcessed = true
            setWallpaperWithPosition(
                activity,
                wallpaperManager,
                bmp,
                flags
            )
        }.invokeOnCompletion {
            isBeingProcessed = false
            isSheetOpen = false
            Toast.makeText(
                context,
                "Wallpaper set successfully",
                Toast.LENGTH_SHORT
            ).show()
        }
    } ?: run {
        // Handle the case where context is not a ComponentActivity
        isBeingProcessed = false
        isSheetOpen = false
        Toast.makeText(
            context,
            "Failed to set wallpaper",
            Toast.LENGTH_SHORT
        ).show()
    }
s
So your dialog never shows, is that the problem? Does the whole thing happen fast enough that it doesn't get a chance to show?
n
That's right, it does not show unless I add a delay like this:
Copy code
isBeingProcessed = true
                            scope.launch {
                               delay(500)
                                wallpaperManager.setBitmap(
                                    bmp, null, true, flags
                                )
                            }
Then it shows but the animation gets stuck/is frozen
The wallpaper process takes several seconds, about 10 I would say, so it's not that.
s
Is your CoroutineScope just from rememberCoroutineScope here? This whole thing looks quite odd. If you do
launch(Dispatchers.Default)
so the wallpaper stuff does not run on the main thread, does that change anything?
🙏 1
n
I've just tried with
Copy code
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
and it is working as it should
Yes,
launch(Dispatchers.Default)
works well.
Thanks! So does my code look odd?
s
No nothing looks out of the ordinary, and I don't know what setBitmap does internally, but looks like it was just hogging the main thread somehow in a way that the compose state didn't even get a chance to invalidate itself and have the UI pickup the new state. I can't say I've seen this before in my code, but I also haven't done much with wallpapers, bitmaps etc
n
Thanks a lot, your help is much appreciated.