Hi <@U2JKKPMEE>, I used `@Preview` annotations in ...
# koin
k
Hi @arnaud.giuliani, I used
@Preview
annotations in my function, but I am getting error on design issues message.
Copy code
This preview was unable to find a CompositionLocal. You might need to define it so it can render correctly. Show Exception
I tried to click on Show Exception it gives me another error
Copy code
java.lang.IllegalStateException: KoinApplication has not been started
    at org.koin.core.context.GlobalContext.get(GlobalContext.kt:36)
    at com.abc.app.bloodpressure.composables.BloodPressureConnectionScreenKt.BluetoothConnectionContentStateful(BloodPressureConnectionScreen.kt:78)
    at com.abc.app.bloodpressure.composables.BloodPressureConnectionScreenKt.BluetoothConnectionContent(BloodPressureConnectionScreen.kt:25)
    at com.abc.app.bloodpressure.composables.BluetoothPairScreenKt.PairContentPreview(BluetoothPairScreen.kt:202)
    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.ComposableInvoker.invokeComposableMethod(ComposableInvoker.kt:155)
    at androidx.compose.ui.tooling.ComposableInvoker.invokeComposable(ComposableInvoker.kt:195)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.kt:590)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.kt:588)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.kt:625)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.kt:583)
    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:228)
    at androidx.compose.ui.tooling.InspectableKt.Inspectable(Inspectable.kt:61)
    at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.kt:531)
    at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.kt:530)
    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:228)
    at androidx.compose.ui.tooling.ComposeViewAdapter.WrapPreview(ComposeViewAdapter.kt:525)
    at androidx.compose.ui.tooling.ComposeViewAdapter.access$WrapPreview(ComposeViewAdapter.kt:124)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.kt:583)
    at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.kt:580)
    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:402)
    at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:248)
    at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:247)
    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:228)
    at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:177)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:123)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122)
    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:228)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:114)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:157)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:156)
    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:228)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:156)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:140)
    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.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:74)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3193)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3183)
    at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:252)
    at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source)
    at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3183)
    at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3119)
    at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:584)
    at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:811)
    at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
    at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1015)
    at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131)
    at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182)
    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)
    at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:202)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
    at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1102)
    at android.view.View.dispatchAttachedToWindow(View.java:20753)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
    at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:58)
    at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:366)
    at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:436)
    at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:121)
    at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:717)
    at com.android.tools.idea.rendering.RenderTask.lambda$inflate$9(RenderTask.java:873)
    at com.android.tools.idea.rendering.RenderExecutor$runAsyncActionWithTimeout$3.run(RenderExecutor.kt:192)
    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:829)
I am adding code here. PairContentPreview
Copy code
@Preview(showBackground = true)
@Composable
fun PairContentPreview() {
    BluetoothConnectionContent()
}
BluetoothConnectionContent
Copy code
@Composable
fun BluetoothConnectionContent() {
    BluetoothConnectionContentStateful()
}
BluetoothConnectionContentStateful
Copy code
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun BluetoothConnectionContentStateful(
    context: Context = LocalContext.current,
    viewModel: BloodPressurePairViewModel = getViewModel(),
) {
  // xyz in here
}
Does anyone know what is the problem in here? build.gradle
Copy code
// compose
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.foundation:foundation-layout:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.runtime:runtime:$compose_version"
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
implementation "androidx.activity:activity-compose:$compose_activity"
implementation "com.google.accompanist:accompanist-pager:$accompanist_version"
implementation "com.google.accompanist:accompanist-pager-indicators:$accompanist_version"
implementation "com.google.accompanist:accompanist-permissions:$accompanist_version"
androidTestImplementation "androidx.compose.ui:ui-test:$compose_version"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"

// koin
implementation "io.insert-koin:koin-android:$koin_version"
implementation "io.insert-koin:koin-androidx-workmanager:$koin_version"
implementation "io.insert-koin:koin-androidx-compose:$koin_compose_version"
testImplementation "io.insert-koin:koin-test-junit4:$koin_version"
testImplementation "io.insert-koin:koin-test:$koin_version"
Version are below
Copy code
koin_version = "3.2.2"
    koin_compose_version = "3.2.1"
    compose_version = '1.2.1'
    compose_compiler_version = '1.3.2'
    compose_activity = "1.6.0"
Thanks
j
Usually you should split up your components into stateful and stateless parts. This way you do not need any koin related stuff in your preview and you can populate your stateless component in different previews with different states. To give an example - we have per file: ExampleRoute: uses koin for dependency injection; renders ExampleScreen with injected values ExampleScreen: stateless componet ExamplePreview (or multiple): renders ExampleScreen with mock values; wrapped in Theme
k
So you are saying like this
Copy code
@Preview(showBackground = true)
@Composable
fun PairContentPreview() {
    AbcTheme {
        BluetoothConnectionContentStateful()
    }
}
with
Copy code
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun BluetoothConnectionContentStateful(
    context: Context = LocalContext.current,
    viewModel: BloodPressurePairViewModel = koinViewModel()
) { // xyz }
like this ?
j
Nope, in the Preview you only use your state less component with mock values (no viewmodel etc.).
k
okk got it now
Thank you so much
199 Views