JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.33k stars 1.18k forks source link

Compose for Desktop doesn't emit lifecycle events, only states #4835

Closed SebastianAigner closed 6 months ago

SebastianAigner commented 6 months ago

1.6.10-rc03.

iOS:

Screenshot 2024-05-19 at 11 28 03

Desktop:

Screenshot 2024-05-19 at 11 28 27

Observed via:

@Composable
fun LifecycleLogger() {
    val lc = LocalLifecycleOwner.current
    LaunchedEffect(lc) {
        launch {
            lc.lifecycle.currentStateFlow.collect {
                println("New State: $it")
            }
        }
        launch {
            lc.lifecycle.eventFlow.collect {
                println("New Event: $it")
            }
        }
    }
}
zsmb13 commented 6 months ago

Looking at the impl of eventFlow:

public val Lifecycle.eventFlow: Flow<Lifecycle.Event>
    get() = callbackFlow {
        val observer = LifecycleEventObserver { _, event ->
            trySend(event)
        }.also { addObserver(it) }

        awaitClose { removeObserver(observer) }
    }.flowOn(Dispatchers.Main.immediate)

Apparently it uses Dispatchers.Main, which is not available if you don't add coroutines-swing to the project explicitly. Adding this dependency fixes the issue:

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.8.1")
SebastianAigner commented 6 months ago

Very strange that I'm seeing no indication (warning, error, log output) indicating this.

MatkovIvan commented 6 months ago

It's expected because kotlinx-coroutines-swing is optional. I'll check why a warning message is missed + make sure that it's desired in docs

MatkovIvan commented 6 months ago

Rechecked what's going on here.

Compose for Desktop doesn't emit lifecycle events

It does. Even without this extra dependency. You can receive it via:

lifecycle.addObserver(object : LifecycleEventObserver {
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        println("New Event: $event")
    }

})

Very strange that I'm seeing no indication (warning, error, log output) indicating this.

It looks like behavior of flowOn function + missed Dispatchers.Main. Example:

flowOf(1, 2, 3)
    .flowOn(Dispatchers.Main.immediate)
    .collect {
        println("collect: $it")
    }

Will print nothing and hang on collect function without any exceptions. I guess it is out of the scope of Compose Multiplatfrom repo, but maybe worth creating YT issue for coroutines library.

okushnikov commented 3 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.