Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack Compose Preview not working when using Koin for Dependency Injection

I want to use Jetpack Compose in my App. I am already using Koin for DI. Because I have a lot of convenience methods in my BaseFragment I want to inherit from it and build the corresponding view with compose.

Now the Problem is that when using DI in the BaseFragment and inheriting from it the preview of the composable wont be shown and following error Message appears:

Error Message in console of preview

and following exception is thrown:

java.lang.IllegalStateException: KoinApplication has not been started
    at org.koin.core.context.GlobalContext.get(GlobalContext.kt:36)
    at org.koin.java.KoinJavaComponent.getKoin(KoinJavaComponent.kt:122)
    at org.koin.java.KoinJavaComponent.get(KoinJavaComponent.kt:87)
    at org.koin.java.KoinJavaComponent.get$default(KoinJavaComponent.kt:81)
    at org.koin.java.KoinJavaComponent.get(KoinJavaComponent.kt)
    ...

My BaseFragment looks something like this

public abstract class BaseFragment {


    private final ActiveViewIdInteractor activeViewIdInteractor =
            new ActiveViewIdInteractor(KoinJavaComponent.get(ActiveViewIdService.class));
...

and my Fragment which inherits looks something like this

class ComposeDemoFragment: BaseFragment() {
   ...

   @Composable
    fun ComposeDemoFragmentContent() {
        Text(text = "Hello World",
            Modifier
                .fillMaxWidth()
                .background(Color.Cyan)
        )
    }

    @Preview
    @Composable
    private fun Preview() {
        ComposeDemoFragmentContent()
    }

If using the exact same preview in a Fragment which doesn't inherit from BaseFragment everything works fine. I already included the dependency for "Koin for Compose" and also tried using CoKoin. At this Point I don't know what to do with the error Message or if the error Message is even barely related to the actual Problem.

Is this a Bug or is there a way to bypass this error?

like image 896
Lukas Schüler Avatar asked Dec 05 '25 15:12

Lukas Schüler


2 Answers

There is a fairly easy workaround for this at the current time of writing with the latest version of Koin.

If you just want to preview a composable with a single VM, use state hoisting and preview the composable that just depends on the state. I had a more complex scenario where I had composable within my screen that had it's own view model so this wasn't an option.

First, define a preview Koin module and create an instance of the view mode:

val previewModule = module {
    single { MyViewModel(SavedStateHandle(emptyMap()), get(), ...) }
    ...
}

Then, create your preview using KoinApplication and your preview module:

@Preview
@Composable
fun MyPreview() {
    // If you need Context
    val context = LocalContext.current

    KoinApplication(application = {
        // If you need Context
        androidContext(context)
        modules(my + other + modules + previewModule)
    }) {
        MyComposable()
    }
}

Unfortunately it doesn't work for multiple previews because you can only add KoinApplication once, but you can add a check for an existing Koin context (as KoinApplication does internally), such as this example which amends the above to create light and dark previews:

@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun MyPreview() {
    if (KoinPlatformTools.defaultContext().getOrNull() == null) {
        // If you need Context
        val context = LocalContext.current

        KoinApplication(application = {
            // If you need Context
            androidContext(context)
            modules(my + other + modules + previewModule)
        }) {
            MyComposable()
        }
    } else {
        MyComposable()
    }
}
like image 184
Philio Avatar answered Dec 07 '25 03:12

Philio


This happens because your @Preview function is inside your Activity. And you probably have an injected member there.

Move it to the root of the file, outside the activity class, and the preview will be rendered without errors.

like image 30
Mister Smith Avatar answered Dec 07 '25 04:12

Mister Smith



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!