compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

LocalLifecycleOwner not declared on Desktop

Open rwst opened this issue 2 years ago • 6 comments

Describe the bug

  1. Create new Compose Multiplatform project, click "Multiple Platforms", JDK 15
  2. In android/src/main/java/com/example/android/MainActivity.kt insert: import androidx.compose.ui.platform.LocalLifecycleOwner --- no problem
  3. In desktop/src/jvmMain/kotlin/Main.kt insert: import androidx.compose.ui.platform.LocalLifecycleOwner --- not found

Affected platforms

  • Desktop

Versions

  • Kotlin version*: 223-1.8.0-release-345-IJ8836.41
  • Compose Multiplatform version*: 1.4.0
  • OS version(s)* (required for Desktop and iOS issues): OpenSuSE Linux Leap 15.2
  • OS architecture (x86 or arm64): x64
  • JDK (for desktop issues): 15

Expected behavior LocalLifecycleOwner should be declared on Desktop

Additional context I would like to use this code:

@Composable
fun ComposableLifecycle(
    lifeCycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    onEvent: (LifecycleOwner, Lifecycle.Event) -> Unit
) {
    DisposableEffect(lifeCycleOwner) {
        val observer = LifecycleEventObserver { source, event ->
            onEvent(source, event)
        }
        lifeCycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifeCycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

rwst avatar Mar 24 '23 12:03 rwst

The question here is how to determine onCreate/onStart/onResume/ and the counterparts onPause/onStop/onDestroy in a Desktop App? If the lifecycle was simpler, like onCreate/onStart/onStop/onDestroy Then you could use the WindowState.isMinimized to track started/stopped. But the original Android lifecycle has too many events, so it makes it harder to port it into other platforms. You can manually create a lifecycle based on the window isMinimized state and provide it as a CompositionLocal and use it as in your code.

pablichjenkov avatar Mar 24 '23 15:03 pablichjenkov

I could do that manually in my app. Also I would like to make a PR so that the declaration is no longer missing on Desktop, but at the moment, I don't have the experience to do that.

rwst avatar Mar 24 '23 17:03 rwst

Like I said, I believe it is a subject that will require some consensus. It is right that Android APIs are really well designed but some of them are a bit overloaded and centered around a mobile device with low memory restrictions. It is hard to find common ground in order to be able to come up with an interface that pleases all the platforms. I do believe the Lifecycle API should be ported to the common compose API but it has to be sliced up. For instance, removing onResume/onPause.

pablichjenkov avatar Mar 24 '23 19:03 pablichjenkov

I think there is another reason why the LocalLifecycleOwner is not implemented for desktop yet (not known to me though). I don't think that mapping the functions is a problem at all, like I could think of the following mapping:

Lifecycle Event Moment of Execution (Desktop)
onCreate When the window is executed for the first time
onStart When the window is opened (not minimized)
onResume When the window is focused (currently selected and in foreground)
onPause When the window looses focus (not currently in foreground)
onStop When the window is minimized
onDestroy When the window is closed

The same behavior applies to Android apps if you think of an app / activity as a window. Additionally, it would also be interesting to include the system tray in the lifecycle states on desktop, if not handled as separate lifecycle owner of course.

However, an interesting and lifecycle-aware implementation provides the MVIKotlin Framework (see Binding and Lifecycle). Maybe using that as a workaround could provide a solution for your code?

malliaridis avatar Mar 24 '23 19:03 malliaridis

Yeah you're right, the focus does map well to resume/pause. I know iOS UiViewController can be mapped too, not sure about the 'browser'. Perhaps as you said, the reason might be other priorities.

pablichjenkov avatar Mar 24 '23 20:03 pablichjenkov

However, an interesting and lifecycle-aware implementation provides the MVIKotlin Framework (see Binding and Lifecycle).

MVIKotlin uses Essenty library which provides Lifecycle, as well as other useful things.

If you use Decompose, then it can control the Lifecycle automatically (or you can control it manually however you want). Otherwise, you can still use Lifecycle from Essenty.

That's not an official solution, but seems working.

arkivanov avatar Mar 28 '23 19:03 arkivanov

Implemented in https://github.com/JetBrains/compose-multiplatform-core/pull/1198, and available in the latest 1.6.10 dev build

MatkovIvan avatar Apr 04 '24 06:04 MatkovIvan