For CMP what is the current state of Previews in c...
# multiplatform
v
For CMP what is the current state of Previews in common src code, it is possible to use them with string and drawable resources inside the composables? I'm getting an errors and trying to understand if it's my configuration issue or still the current state of CMP previews?
p
Works fine on my end but I just need to rebuild/refresh manually every preview on any change. It doesn't refresh automatically.
v
@Pavlos Common composable + drawable and string resources inside the composable that is in preview? Is it AS narwhal or something different?
p
Yes, on AS narwhal, do you mind share a test compostable preview screen that doesn't work on your end?
v
@Pavlos sure thing, even the simple one like this
Copy code
@Composable
@Preview
fun TestPreview() {
    Text(
        text = stringResource(Res.string.listing_title)
    )
}
Gives me this stacktrace:
Copy code
java.lang.NullPointerException
	at org.jetbrains.compose.resources.ResourceReader_androidKt$getPlatformResourceReader$1.getResourceAsStream(ResourceReader.android.kt:75)
	at org.jetbrains.compose.resources.ResourceReader_androidKt$getPlatformResourceReader$1.readPart(ResourceReader.android.kt:34)
	at org.jetbrains.compose.resources.StringResourcesUtilsKt$getStringItem$2.invokeSuspend(StringResourcesUtils.kt:30)
	at org.jetbrains.compose.resources.StringResourcesUtilsKt$getStringItem$2.invoke(StringResourcesUtils.kt)
	at org.jetbrains.compose.resources.StringResourcesUtilsKt$getStringItem$2.invoke(StringResourcesUtils.kt)
	at org.jetbrains.compose.resources.AsyncCache$getOrLoad$2$deferred$1$1.invokeSuspend(AsyncCache.kt:19)
	at _layoutlib_._internal_.kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at _layoutlib_._internal_.kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at _layoutlib_._internal_.kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:263)
	at _layoutlib_._internal_.kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:94)
	at _layoutlib_._internal_.kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:70)
	at _layoutlib_._internal_.kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at _layoutlib_._internal_.kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
	at _layoutlib_._internal_.kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at org.jetbrains.compose.resources.ResourceState_blockingKt.rememberResourceState(ResourceState.blocking.kt:15)
	at org.jetbrains.compose.resources.StringResourcesKt.stringResource(StringResources.kt:27)
	at com.thredup.core.compose.button.TuButtonKt.TestPreview(TuButton.kt:468)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at androidx.compose.ui.tooling.ComposableInvoker.invokeComposableMethod(ComposableInvoker.jvm.kt:185)
	at androidx.compose.ui.tooling.ComposableInvoker.invokeComposable(ComposableInvoker.jvm.kt:222)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1$1.invoke(ComposeViewAdapter.android.kt:478)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1$1.invoke(ComposeViewAdapter.android.kt:476)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.android.kt:519)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.android.kt:469)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.tooling.InspectableKt.Inspectable(Inspectable.android.kt:58)
	at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.android.kt:414)
	at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.android.kt:413)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.tooling.ComposeViewAdapter.WrapPreview(ComposeViewAdapter.android.kt:408)
	at androidx.compose.ui.tooling.ComposeViewAdapter.access$WrapPreview(ComposeViewAdapter.android.kt:123)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.android.kt:469)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.android.kt:466)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:431)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:216)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:140)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:139)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:384)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:139)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:123)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.internal.Utils_jvmKt.invokeComposable(Utils.jvm.kt:27)
	at androidx.compose.runtime.ComposerImpl.doCompose-aFTiNEg(Composer.kt:3694)
	at androidx.compose.runtime.ComposerImpl.composeContent--ZbOJvo$runtime_release(Composer.kt:3616)
	at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:792)
	at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1132)
	at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:677)
	at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:616)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:123)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1963)
	at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:168)
	at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:313)
	at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:191)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:121)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:2042)
	at android.view.View.dispatchAttachedToWindow(View.java:23071)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3518)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3525)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3525)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3525)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3525)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3525)
	at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:69)
	at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:362)
	at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:462)
	at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:125)
	at com.android.tools.rendering.RenderTask.createRenderSession(RenderTask.java:829)
	at com.android.tools.rendering.RenderTask.lambda$inflate$7(RenderTask.java:977)
	at com.android.tools.rendering.RenderExecutor.runAsyncActionWithTimeout$lambda$12(RenderExecutor.kt:217)
	at com.android.tools.rendering.RenderExecutor$PriorityRunnable.run(RenderExecutor.kt:338)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
p
Hmm, do you have your composeResources file?
v
Yep, that's where they are
Hm, it doesn't even work in Android source set, hovewer based on this page
Starting with Compose Multiplatform 1.8.2, all multiplatform resources are packed into Android assets. This enables Android Studio to generate previews for Compose Multiplatform composables in Android source sets.
Copy code
kotlin {
  androidLibrary {
    androidResources.enable = true
  }
}
I also have this in my module since it's a library module rather than application, could it be the case?
i
Hey, that should be working fine. Please make sure you're using AGP 8.7.3 or above, also: there were changes in this regard. Otherwise, feel free to raise an issue in the KMT tracker with a simple reproducer project!
v
@Ilia Bogdanovich [JetBrains] ok, I'm using 8.10.1 + compose 1.8.2 + kotlin 2.2, maybe there is something missing from library list?
i
The setup you have should be fine. Please raise an issue with a reproducer in the KMT tracker.