Jetpack Compose Preview failing with LocalDate.now() from ThreeTen
Asked Answered
T

1

6

Rendering the Jetpack Compose Preview fails when we have some code calling LocalDate.now() from it. We have tried setting a locale on the preview but that does not help, and we have not found any other way to set context information on the Preview.

How can we make that work?

Preview render problem stacktrace:

org.threeten.bp.zone.ZoneRulesException: No time-zone data files registered at org.threeten.bp.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:165) at org.threeten.bp.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:122) at org.threeten.bp.ZoneRegion.ofId(ZoneRegion.java:143) at org.threeten.bp.ZoneId.of(ZoneId.java:358) at org.threeten.bp.ZoneId.of(ZoneId.java:286) at org.threeten.bp.ZoneId.systemDefault(ZoneId.java:245) at org.threeten.bp.Clock.systemDefaultZone(Clock.java:137) at org.threeten.bp.LocalDate.now(LocalDate.java:165) at xxx.ui.shared.formatter.OrderDateFormatter.getFormattedTimes(OrderDateFormatter.kt:12) at xxx.model.Pickup.displayCreatedTime(Pickup.kt:55) at xxx.ui.orderStatus.pickups.PickupsListKt.DateRows(PickupsList.kt:268) at xxx.ui.orderStatus.pickups.PickupsListKt.PickupPanelDetails(PickupsList.kt:129) at xxx.ui.orderStatus.pickups.PickupsListKt.PickupPanel(PickupsList.kt:78) at xxx.ui.orderStatus.pickups.PickupsListKt$PickupsList$1$1.invoke(PickupsList.kt:51) at xxx.ui.orderStatus.pickups.PickupsListKt$PickupsList$1$1.invoke(PickupsList.kt:49) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at xxx.ui.shared.composables.LoadingComposableKt.LoadingComposable(LoadingComposable.kt:39) at xxx.ui.orderStatus.pickups.PickupsListKt.PickupsList(PickupsList.kt:49) at xxx.ui.orderStatus.pickups.ComposableSingletons$PickupsListKt$lambda-1$1.invoke(PickupsList.kt:337) at xxx.ui.orderStatus.pickups.ComposableSingletons$PickupsListKt$lambda-1$1.invoke(PickupsList.kt:336) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at xxx.ui.shared.appTheme.AppThemeKt$AppTheme$1.invoke(AppTheme.kt:56) at xxx.ui.shared.appTheme.AppThemeKt$AppTheme$1.invoke(AppTheme.kt:55) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:252) at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81) at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72) at xxx.ui.shared.appTheme.AppThemeKt.AppTheme(AppTheme.kt:55) at xxx.ui.orderStatus.pickups.PickupsListKt.DefaultPickupsListPreview(PickupsList.kt:336) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at androidx.compose.ui.tooling.CommonPreviewUtils.invokeComposableMethod(CommonPreviewUtils.kt:149) at androidx.compose.ui.tooling.CommonPreviewUtils.invokeComposableViaReflection$ui_tooling_release(CommonPreviewUtils.kt:188) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.kt:571) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.kt:569) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.kt:608) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.kt:564) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.ui.tooling.InspectableKt.Inspectable(Inspectable.kt:64) at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.kt:513) at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.kt:512) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.ui.tooling.ComposeViewAdapter.WrapPreview(ComposeViewAdapter.kt:508) at androidx.compose.ui.tooling.ComposeViewAdapter.access$WrapPreview(ComposeViewAdapter.kt:121) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.kt:564) at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.kt:561) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:384) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:228) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:227) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:148) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:114) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:113) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:106) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:162) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:161) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:161) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:144) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3336) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2583) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2579) at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2572) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2523) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:476) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:727) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:432) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:144) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:135) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:733) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:135) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:187) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:196) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:135) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:820) at android.view.View.dispatchAttachedToWindow(View.java:20479) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496) at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:44) at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:360) at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:431) at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:141) at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:714) at com.android.tools.idea.rendering.RenderTask.lambda$inflate$7(RenderTask.java:870) at com.android.tools.idea.rendering.RenderExecutor$runAsyncActionWithTimeout$2.run(RenderExecutor.kt:187) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)

Theadora answered 7/10, 2021 at 6:52 Comment(1)
Does this answer your question? Is the call to AndroidThreeTen.init() mandatory?Haywood
T
13

And just after posting the question we found a solution.

Just add this line at the start of each preview method needing it:

AndroidThreeTen.init(LocalContext.current)

It would be nice with a way to setup a method to be called as setup for all previews, it might be something to hope for in comming releases.

Theadora answered 7/10, 2021 at 7:10 Comment(1)
One can argue that a previewable composable should not be dealing with dates and times directly. Something else, such as a viewmodel, would handle the date/time conversion to data that is more directly rendered (e.g., string representations to display, booleans for controlling icons). That improves testability, with a side benefit of not needing to initialize AndroidThreeTen.Demagogue

© 2022 - 2024 — McMap. All rights reserved.