ITmob-Ly
发布于 2024-04-17 / 139 阅读
0

Android Exception - IllegalStateException: CompositionLocal LocalConfiguration not present

使用 Jetpack Glance 实现 Widget 时偶尔会遇到 IllegalStateException 异常,比如:IllegalStateException: CompositionLocal LocalConfiguration not present 或者 IllegalStateException: CompositionLocal LocalDensity not present

Jetpack Glance 通过提供的可组合项,在我们使用时隐藏了 RemoteView,无需直接操作 RemoteView,但是最终还是会转换为 RemoteView 来渲染。

这是因为 Jetpack Glance 实现 Widget/小部件的原理是它提供了一组独立的可组合项供我们使用,其提供的组件不能与 Jetpack Compose 库互相操作,如果使用的可组合项不是来自 Jetpack Glance API 则会遇到类似 IllegalStateException: CompositionLocal * not present 异常

例如:

  • 在 Jetpack Glance 实现 widget 时通过 Jetpack Compose 的 stringResource() 可组合项加载字符串资源,运行时则会抛出异常:IllegalStateException: CompositionLocal LocalConfiguration not present

    应使用 Jetpack Glance 提供的 API:*LocalContext*.current.getString() 来加载字符串资源。

  • 在 Jetpack Glance 实现 widget 时通过 Jetpack Compose 的 LocalDensity 进行屏幕密度相关操作时,会抛出异常:IllegalStateException: CompositionLocal LocalDensity not present

    目前的 Jetpack Glance 版本()没有提供 Glance 版本的 LocalDensity。

如下是抛出两种异常代码和异常日志:

1. IllegalStateException: CompositionLocal LocalConfiguration not present

package cn.itmob.glance

class SampleGlanceAppWidget : GlanceAppWidget() {

    //...

    @Composable
    fun Greeting() {
        Text(text = stringResource(R.string.app_name))
    }
}

上面代码抛出的异常日志:

WM-WorkerWrapper        cn.itmob.glance             E  Work [ id=f5579d86-cdff-4f7c-8468-291da5542dbc, tags={ androidx.glance.session.SessionWorker } ] failed because it threw an exception/error
    java.util.concurrent.ExecutionException: java.lang.IllegalStateException: CompositionLocal LocalConfiguration not present
        at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
        at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
        at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:311)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
        at java.lang.Thread.run(Thread.java:1012)
    Caused by: java.lang.IllegalStateException: CompositionLocal LocalConfiguration not present
        at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.noLocalProvidedFor(AndroidCompositionLocals.android.kt:164)
        at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.access$noLocalProvidedFor(AndroidCompositionLocals.android.kt:1)
        at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$LocalConfiguration$1.invoke(AndroidCompositionLocals.android.kt:44)
        at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$LocalConfiguration$1.invoke(AndroidCompositionLocals.android.kt:43)
        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:88)
        at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2049)
        at androidx.compose.ui.res.Resources_androidKt.resources(Resources.android.kt:35)
        at androidx.compose.ui.res.StringResources_androidKt.stringResource(StringResources.android.kt:34)
        at cn.itmob.glance.SampleGlanceAppWidget$Greeting$1.invoke(SampleGlanceAppWidget.kt:45)
        at cn.itmob.glance.SampleGlanceAppWidget$Greeting$1.invoke(SampleGlanceAppWidget.kt:44)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.glance.layout.ColumnKt.Column-K4GKKTE(Column.kt:97)
        at cn.itmob.glance.SampleGlanceAppWidget.Greeting(SampleGlanceAppWidget.kt:42)
        at cn.itmob.glance.SampleGlanceAppWidget.access$Greeting(SampleGlanceAppWidget.kt:22)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2$1.invoke(SampleGlanceAppWidget.kt:28)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2$1.invoke(SampleGlanceAppWidget.kt:27)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.glance.GlanceThemeKt.GlanceTheme(GlanceTheme.kt:44)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2.invoke(SampleGlanceAppWidget.kt:27)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2.invoke(SampleGlanceAppWidget.kt:26)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.glance.appwidget.SizeBoxKt$SizeBox$1.invoke(SizeBox.kt:127)
        at androidx.glance.appwidget.SizeBoxKt$SizeBox$1.invoke(SizeBox.kt:74)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
WM-WorkerWrapper        cn.itmob.glance             E  	at androidx.glance.appwidget.SizeBoxKt.SizeBox-IbIYxLY(SizeBox.kt:74)
        at androidx.glance.appwidget.SizeBoxKt.ForEachSize-eVKgIn8(SizeBox.kt:114)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1$1.invoke(AppWidgetSession.kt:110)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1$1.invoke(AppWidgetSession.kt:90)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1.invoke(AppWidgetSession.kt:85)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1.invoke(AppWidgetSession.kt:84)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:169)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2468)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2737)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3352)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3303)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:781)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1097)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:124)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:569)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:537)
        at androidx.compose.runtime.BroadcastFrameClock$FrameAwaiter.resume(BroadcastFrameClock.kt:42)
        at androidx.compose.runtime.BroadcastFrameClock.sendFrame(BroadcastFrameClock.kt:71)
        at androidx.glance.session.InteractiveFrameClock.sendFrame(InteractiveFrameClock.kt:127)
        at androidx.glance.session.InteractiveFrameClock.access$sendFrame(InteractiveFrameClock.kt:39)
        at androidx.glance.session.InteractiveFrameClock$onNewAwaiters$2.invokeSuspend(InteractiveFrameClock.kt:117)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at android.os.Handler.handleCallback(Handler.java:958)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:205)
        at android.os.Looper.loop(Looper.java:294)
        at android.app.ActivityThread.main(ActivityThread.java:8177)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
WM-WorkerWrapper        cn.itmob.glance             I  Worker result FAILURE for Work [ id=f5579d86-cdff-4f7c-8468-291da5542dbc, tags={ androidx.glance.session.SessionWorker } ]

2. IllegalStateException: CompositionLocal LocalDensity not present

package cn.itmob.glance

class SampleGlanceAppWidget : GlanceAppWidget() {

    //...

    @Composable
    fun Greeting() {
        val widthPx = with(LocalDensity.current) { LocalSize.current.width.toPx() }
        Text(text = "https://itmob.cn")
    }
}

上面代码抛出的异常日志:

WM-WorkerWrapper        cn.itmob.glance             E  	Work [ id=5cf91d87-22e6-468b-8f7a-16e2153a9b90, tags={ androidx.glance.session.SessionWorker } ] failed because it threw an exception/error
    java.util.concurrent.ExecutionException: java.lang.IllegalStateException: CompositionLocal LocalDensity not present
        at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
        at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
        at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:311)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
        at java.lang.Thread.run(Thread.java:1012)
    Caused by: java.lang.IllegalStateException: CompositionLocal LocalDensity not present
        at androidx.compose.ui.platform.CompositionLocalsKt.noLocalProvidedFor(CompositionLocals.kt:220)
        at androidx.compose.ui.platform.CompositionLocalsKt.access$noLocalProvidedFor(CompositionLocals.kt:1)
        at androidx.compose.ui.platform.CompositionLocalsKt$LocalDensity$1.invoke(CompositionLocals.kt:83)
        at androidx.compose.ui.platform.CompositionLocalsKt$LocalDensity$1.invoke(CompositionLocals.kt:82)
        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:88)
        at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2049)
        at cn.itmob.glance.SampleGlanceAppWidget.Greeting(SampleGlanceAppWidget.kt:50)
        at cn.itmob.glance.SampleGlanceAppWidget.access$Greeting(SampleGlanceAppWidget.kt:21)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2$1.invoke(SampleGlanceAppWidget.kt:27)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2$1.invoke(SampleGlanceAppWidget.kt:26)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.glance.GlanceThemeKt.GlanceTheme(GlanceTheme.kt:44)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2.invoke(SampleGlanceAppWidget.kt:26)
        at cn.itmob.glance.SampleGlanceAppWidget$provideGlance$2.invoke(SampleGlanceAppWidget.kt:25)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.glance.appwidget.SizeBoxKt$SizeBox$1.invoke(SizeBox.kt:127)
        at androidx.glance.appwidget.SizeBoxKt$SizeBox$1.invoke(SizeBox.kt:74)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.glance.appwidget.SizeBoxKt.SizeBox-IbIYxLY(SizeBox.kt:74)
        at androidx.glance.appwidget.SizeBoxKt.ForEachSize-eVKgIn8(SizeBox.kt:114)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1$1.invoke(AppWidgetSession.kt:110)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1$1.invoke(AppWidgetSession.kt:90)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1.invoke(AppWidgetSession.kt:85)
        at androidx.glance.appwidget.AppWidgetSession$provideGlance$1.invoke(AppWidgetSession.kt:84)
WM-WorkerWrapper        cn.itmob.glance             E  	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:169)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2468)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2737)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3352)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3303)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:781)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1097)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:124)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:569)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:537)
        at androidx.compose.runtime.BroadcastFrameClock$FrameAwaiter.resume(BroadcastFrameClock.kt:42)
        at androidx.compose.runtime.BroadcastFrameClock.sendFrame(BroadcastFrameClock.kt:71)
        at androidx.glance.session.InteractiveFrameClock.sendFrame(InteractiveFrameClock.kt:127)
        at androidx.glance.session.InteractiveFrameClock.access$sendFrame(InteractiveFrameClock.kt:39)
        at androidx.glance.session.InteractiveFrameClock$onNewAwaiters$2.invokeSuspend(InteractiveFrameClock.kt:117)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at android.os.Handler.handleCallback(Handler.java:958)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:205)
        at android.os.Looper.loop(Looper.java:294)
        at android.app.ActivityThread.main(ActivityThread.java:8177)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
WM-WorkerWrapper        cn.itmob.glance             I  Worker result FAILURE for Work [ id=5cf91d87-22e6-468b-8f7a-16e2153a9b90, tags={ androidx.glance.session.SessionWorker } ]