rememberPreferenceState doesn't work with new androidx.lifecycle 2.8.0
Expected Behavior
Updating dependency from lifecycle 2.7.0 to 2.8.0 would hopefully "just work".
https://developer.android.com/jetpack/androidx/releases/lifecycle#version_28_2
Actual Behavior
As soon as a screen with preferences from this library is used with updated lifecycle dependency the app crashed with the following stack trace example 1 with direct usage of rememberPreferenceState:
java.lang.IllegalStateException: CompositionLocal LocalLifecycleOwner not present
at androidx.lifecycle.compose.LocalLifecycleOwnerKt$LocalLifecycleOwner$1.invoke(LocalLifecycleOwner.kt:26)
at androidx.lifecycle.compose.LocalLifecycleOwnerKt$LocalLifecycleOwner$1.invoke(LocalLifecycleOwner.kt:25)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at androidx.compose.runtime.LazyValueHolder.getCurrent(ValueHolders.kt:29)
at androidx.compose.runtime.LazyValueHolder.getValue(ValueHolders.kt:31)
at androidx.compose.runtime.CompositionLocalMapKt.read(CompositionLocalMap.kt:90)
at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2135)
at androidx.lifecycle.compose.FlowExtKt.collectAsStateWithLifecycle(FlowExt.kt:183)
at me.zhanghai.compose.preference.PreferenceStateKt.rememberPreferenceState(PreferenceState.kt:35)
...
Stack trace example 2 with indirect usage of rememberPreferenceState using a listPreference:
java.lang.IllegalStateException: CompositionLocal LocalLifecycleOwner not present
at androidx.lifecycle.compose.LocalLifecycleOwnerKt$LocalLifecycleOwner$1.invoke(LocalLifecycleOwner.kt:26)
at androidx.lifecycle.compose.LocalLifecycleOwnerKt$LocalLifecycleOwner$1.invoke(LocalLifecycleOwner.kt:25)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at androidx.compose.runtime.LazyValueHolder.getCurrent(ValueHolders.kt:29)
at androidx.compose.runtime.LazyValueHolder.getValue(ValueHolders.kt:31)
at androidx.compose.runtime.CompositionLocalMapKt.read(CompositionLocalMap.kt:90)
at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2135)
at androidx.lifecycle.compose.FlowExtKt.collectAsStateWithLifecycle(FlowExt.kt:183)
at me.zhanghai.compose.preference.PreferenceStateKt.rememberPreferenceState(PreferenceState.kt:35)
at se.consat.telematics.travelito.ui.screens.ComposableSingletons$AppSettingsScreenKt$lambda-21$1$1$invoke$$inlined$listPreference$default$1.invoke(ListPreference.kt:283)
at se.consat.telematics.travelito.ui.screens.ComposableSingletons$AppSettingsScreenKt$lambda-21$1$1$invoke$$inlined$listPreference$default$1.invoke(ListPreference.kt:80)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.foundation.lazy.LazyListIntervalContent$item$3.invoke(LazyListIntervalContent.kt:59)
Changing dependency back to 2.7.0 and it starts working fine again.
Steps to Reproduce the Problem
- Having in build.gradle.kts:
val lifecycle_version = "2.7.0" // https://developer.android.com/jetpack/androidx/releases/lifecycle
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// ViewModel utilities for Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
// Lifecycles only (without ViewModel or LiveData)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version") //empty since 2.8.0+
// Lifecycle utilities for Compose
implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version")
// Saved state module for ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
// Annotation processor
//kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
// optional - helpers for implementing LifecycleOwner in a Service
implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
Code example 1:
ProvidePreferenceLocals {
Column(...) {
val state: MutableState<Boolean?> = rememberPreferenceState(SettingsKeys.KEY_FORCE_DARK_MODE, null)
Last line there gives the exception in example stack trace 1 above.
Code example 2:
@Composable
fun AppSettingsApp() {
TravelitoTheme {
ProvidePreferenceLocals(
theme = preferenceTheme(categoryColor = MaterialTheme.colorScheme.primary)
) {
AppSettingsScreen()
}
}
}
@Composable
fun AppSettingsScreen() {
Scaffold(...) {
LazyColumn(modifier = Modifier.fillMaxSize(), contentPadding = contentPadding) {
listPreference(
key = SettingsKeys.KEY_FORCE_DARK_MODE,
icon = { Icon(ThemeIcons.DarkMode, "Theme") },
defaultValue = null,
values = listOf(true, false, null),//"Dark", "Light", "Follow System"),
title = { Text(text = "Theme") },
summary = { Text(text = stringResource(themeString(it as Boolean?))) },
valueToText = { AnnotatedString(context.getString(themeString(it as Boolean?))) }
)
..
- Change first line in build.gradle.kts version to 2.8.0
Specifications
- Version:
- Platform: Android 14, Google Pixel 7 Pro
This is a version mismatch issue:
- Compose 1.6 & Lifecycle 2.7:
androidx.compose.ui.platform.LocalLifecycleOwner - Compose 1.7 & Lifecycle 2.8:
androidx.lifecycle.compose.LocalLifecycleOwner
ComposePreference 1.0.0 depends on Lifecycle 2.7
See https://stackoverflow.com/a/78490417 - latest stable Lifecycle (2.8.0) is incompatible with latest stable Compose. I can't depend on unstable Compose in library, so for now you'll need to downgrade Lifecycle on your side, or take one of the workarounds offered in the bug linked in that SO answer.
I'll keep this issue open for awareness, until we have a stable Compose version that's compatible with Lifecycle 2.8.0.
Lifecycle 2.8.2 can be used with any version of Compose now, so closing this issue.