Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support androidx viewmodel for kotlin multiplatform #1826

Closed
Vivecstel opened this issue Mar 21, 2024 · 46 comments
Closed

Support androidx viewmodel for kotlin multiplatform #1826

Vivecstel opened this issue Mar 21, 2024 · 46 comments

Comments

@Vivecstel
Copy link

https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0-alpha03 added view model support for kotlin multiplatform.
Ideally koin should support this also.
Thanks

@fluttertutorialin
Copy link

Can you explain how to add viewmodel library in kmm

@frankois1234
Copy link

frankois1234 commented Apr 3, 2024

Hello,
some reference here

A full demo how to use viewmodel here :

It should be OK that koin move the viewmodel support to KMP.

@ghost
Copy link

ghost commented Apr 4, 2024

The is the official repo used in google codelabe
https://github.com/MatkovIvan/nav_cupcake

@AbdelrahmanEsam
Copy link

@frankois1234 it doesn't work with koin .... iam getting this error

Uncaught Kotlin exception: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'viewModel class Name']'
at 0 shared

also I am creating this viewModel by factory or single ..... I think koin should support the viewModel{} at the common main

@Leedwon
Copy link

Leedwon commented Apr 9, 2024

@AbdelrahmanEsam

Inspired by https://github.com/MatkovIvan/nav_cupcake/blob/master/composeApp/src/commonMain/kotlin/com/matkovivan/nav_cupcake/ViewModels.kt which uses androidx viewmodel. I'm using the following code to make it work with Koin:

ViewModels.kt in commonMain:

internal expect fun <VM : ViewModel> viewModel(
    modelClass: KClass<VM>,
    factory: ViewModelProvider.Factory = rememberViewModelFactory()
): VM

// Can't be private as it causes Exception during IR lowering
@Composable
internal fun rememberViewModelFactory(): ViewModelProvider.Factory {
    val koin = getKoin()
    return remember {
        viewModelFactory {
            initializer { MyViewModel(myDependency = koin.get()) }
            ... // more VM initializers
        }
    }
}

ViewModels.android.kt in androidMain:

@Composable
internal actual fun <VM : ViewModel> viewModel(
    modelClass: KClass<VM>,
    factory: ViewModelProvider.Factory
): VM = androidx.lifecycle.viewmodel.compose.viewModel(modelClass.java, factory = factory)

ViewModels.ios.kt in iosMain:

@Composable
internal actual fun <VM : ViewModel> viewModel(
    modelClass: KClass<VM>,
    factory: ViewModelProvider.Factory
): VM = androidx.lifecycle.viewmodel.compose.viewModel(modelClass, factory = factory)

And wiring it in the Composables:

@Composable
fun MyScreen(
    myViewModel: MyViewModel = viewModel(MyViewModel::class)
) {

}

I doesn't guarantee that it's the most correct approach, but it works and can be a workaround until Koin officially suports it.

@AbdelrahmanEsam
Copy link

@Leedwon the problem is on the ios side not the android one .... android is working perfectly

class DIHelper : KoinComponent {
private val notesViewModel: NotesViewModel by inject()
private val noteDetailsViewModel: NoteDetailsViewModel by inject()

fun getNotesViewModel(): NotesViewModel = notesViewModel
fun getNoteDetailsViewModel(): NoteDetailsViewModel = noteDetailsViewModel

}

this is my DIHelper in the iosMain to access the viewModels in the ios app

@Leedwon
Copy link

Leedwon commented Apr 9, 2024

@AbdelrahmanEsam I see, I'm using Compose Multiplatform, so for me the setup above does the job on both platforms. But if you are having the setup with separate UIs for iOS and Android, then I think you can take a look at joreilly FantasyPremierLeague, he's using VMs with Koin. I haven't checked the whole thing, but this PR might be helpful.

@AbdelrahmanEsam
Copy link

@Leedwon unfortunately his viewModels doesn't have any other injected dependencies (usecases /repositories) so he just take object from it at the view in ios side

@frankois1234
Copy link

frankois1234 commented Apr 9, 2024

The ViewModel in the common Main is more for the Compose Multiplatform than SwiftUI.

Nothing will change for iOS UIKit/SwiftUI.

The best example is https://github.com/joreilly/FantasyPremierLeague.

Also, the usage of Koin viewmodel in the commonMain must be also for Koin annotation.

@AbdelrahmanEsam
Copy link

@frankois1234 that really doesn't work .... I am using the helper in the ios main module and for the android side everything working perfectly .... but when I am trying to run the ios app koin can't inject the viewModel with the following error

org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:

@frankois1234
Copy link

This issue is for demanding the implementation of koin ViewModel support in kmp commonMain project, not how to use it.

As the import org.koin.androidx.viewmodel.dsl.viewModel is not available in commonMain project but the import of androidx.lifecycle.ViewModel is now possible with the latest androidx.lifecycle:lifecycle-viewmodel dependancies

@Vivecstel
Copy link
Author

This issue is for demanding the implementation of koin ViewModel support in kmp commonMain project, not how to use it.

As the import org.koin.androidx.viewmodel.dsl.viewModel is not available in commonMain project but the import of androidx.lifecycle.ViewModel is now possible with the latest androidx.lifecycle:lifecycle-viewmodel dependancies

exactly

@AbdelrahmanEsam
Copy link

@frankois1234 I didn't said that I am using it with koin viewModel ..... actually I am creating it with factory or single in koin .... but koin failed to give me my instance

@AbdelrahmanEsam
Copy link

AbdelrahmanEsam commented Apr 10, 2024

@frankois1234 this happen in the ios side only for some reason I really don't know .... in the android side everything working perfectly

@frankois1234
Copy link

@AbdelrahmanEsam Please make another issue, it's not the target of the current one

@marcellogalhardo
Copy link
Contributor

marcellogalhardo commented Apr 17, 2024

@arnaudgiuliani, now that JetBrains has published their artifact (which includes JS and WASM support), we should be able to add official ViewModel KMP support to Koin.

Note that the new artifact is still experimental, so we might want to wait for it to reach a more stable stage, but we can start exploring it and reporting any challenge we may find to JB.

Please see: https://github.com/JetBrains/compose-multiplatform/releases/tag/v1.6.10-beta01

@PMARZV
Copy link

PMARZV commented Apr 17, 2024

Experimental support for koin viewmodel multiplatform would be helpful!

@arnaudgiuliani
Copy link
Member

Great, let's add it for one of next milestone quickly 💪
thanks @marcellogalhardo

@frankois1234
Copy link

@arnaudgiuliani koin annotations will have the support?

@arnaudgiuliani
Copy link
Member

it should be possible yes 👍

@ronjunevaldoz
Copy link

Following this!

@arnaudgiuliani
Copy link
Member

Work in progress: #1875

@arnaudgiuliani
Copy link
Member

Release in 3.6.0-Beta4 🎉

@ColtonIdle
Copy link

ColtonIdle commented May 17, 2024 via email

@agabeyalioglu
Copy link

Hello @arnaudgiuliani i tried 3.6.0-Beta4

factory {
    ListViewModel(get(), get(named(IODispatcher)))
}

I was creating my viewmodel like this previously. Now if i use viewModelOf(::ListViewModel) how can i specify the dispatcher parameter to use named(IODispatcher)?

@DavidGrygar
Copy link

Hi, can I get and use viewModelOf in commonMain if we use SwiftUI on iOS side? What import/imports is needed for this? I have 3.6.0-Beta4 version.

@arnaudgiuliani
Copy link
Member

Hello @arnaudgiuliani i tried 3.6.0-Beta4

factory {
    ListViewModel(get(), get(named(IODispatcher)))
}

I was creating my viewmodel like this previously. Now if i use viewModelOf(::ListViewModel) how can i specify the dispatcher parameter to use named(IODispatcher)?

you need manual dsl then to describe your qualifier and use named.

@arnaudgiuliani
Copy link
Member

Hi, can I get and use viewModelOf in commonMain if we use SwiftUI on iOS side? What import/imports is needed for this? I have 3.6.0-Beta4 version.

For compose MP for now. Still need a bit of work for Swift integration

@frankois944
Copy link

Hi, can I get and use viewModelOf in commonMain if we use SwiftUI on iOS side? What import/imports is needed for this? I have 3.6.0-Beta4 version.

@DavidGrygar
It's not that simple, take a look at https://github.com/joreilly/FantasyPremierLeague and joreilly/FantasyPremierLeague#231.

You can use a Android ViewModel almost like a SwiftUI ViewModel but you need to manage the lifecycle yourself.

@frankois944
Copy link

frankois944 commented Jun 15, 2024

@DavidGrygar @ColtonIdle
For the iOS developer hear, I made a playground with a lot of interesting things with Koin and MVVM

https://github.com/frankois944/kmp-mvvm-exploration

@romanatexn
Copy link

romanatexn commented Jun 22, 2024

Not sure if this is the best place to ask, but related:
I'm trying 3.6.0-Beta4 and everything looks great, but is it ok to instantiate a kotlin multiplatform viewmodel on iOS using a factory{} inside an Observable object and manually cancel it's scope on deinit of the Observable object?

It seems to be working fine, but I'm afraid of the viewModel comments:
"You should never manually create a [ViewModel] outside of a [ViewModelProvider.Factory]"

Maybe I'm missing something important?

Context:
I want to use the same ViewModel inside Compose using koinViewModel, and iOS SwiftUI using factory

@frankois944
Copy link

@romanatexn
The official Kotlin ViewModel is made to be working on an Android/Compose not a SwiftUI/iOS environment. I think the usage on swift language is kind of experimental as we need to fill the holes.
So, I guess, this rule doesn't apply for Swift.

The most important thing is the respect of the lifecycle of the viewmodel (init()/onCleared()).
The kotlin ViewModel on SwiftUI/iOS target must be used like a SwiftUI ViewModel not like an Android/Compose ViewModel, they can't be used the same way.

@gustavopeq
Copy link

I tried to use the viewModel from 3.6.0-Beta4, and everything seemed to be fine on Android. However, I noticed that whenever I navigate out and back to a specific screen, a new instance of that view model is created. Wasn't it supposed to reuse the viewModel as it was already created previously?
I have this same logic on the Android Native, and it doesn't create multiple instances of the view model. Am I missing something here?
So right now I see the init being called multiple times, even though onCleared is not called at all.

Let me know if that's a different issue.

Thank you...

@frankois944
Copy link

I tried to use the viewModel from 3.6.0-Beta4, and everything seemed to be fine on Android. However, I noticed that whenever I navigate out and back to a specific screen, a new instance of that view model is created. Wasn't it supposed to reuse the viewModel as it was already created previously? I have this same logic on the Android Native, and it doesn't create multiple instances of the view model. Am I missing something here? So right now I see the init being called multiple times, even though onCleared is not called at all.

Let me know if that's a different issue.

Thank you...

Hi, you need to wrap your KMP viewmodel inside an SwiftUI ObservableObject and use it from a @StateObject like an SwiftUI MVVM class.

Take a look at my repo, https://github.com/frankois944/kmp-mvvm-exploration, you will find some inspiration.

@gustavopeq
Copy link

Hey @frankois944, thanks for sharing your repo... I'll look into it.
I understand we still have to do some workaround to get the viewModel to work as expected for iOS, but talking on the Android side, wouldn't that be supposed to work as it is, using the koinViewModel()?

@frankois944
Copy link

frankois944 commented Jul 7, 2024

Oh, I see.
The target need to be specified when talking multiplatform 😃

For Android, The koinViewModel() need to be declared at the top of your compose current screen composable hierarchies, as you can see in my repo on androidApp target.
I also saw this behavior you had if I'm using the koinViewModel() on sub composable element of the screen.

@hoc081098
Copy link
Contributor

hoc081098 commented Jul 9, 2024

@farhazulMullick
Copy link

@arnaudgiuliani
I don't understand how we are making the viewModel lifecycleAware this way. Who would automatically call the onCleared () method of viewModel in android and iOS.

In hiltViewModel() viewModel is attached with NavBackStatckEntry. When backStack is cleared onCleared method of VM is cleared. How this is going to taken care in koin?

@frankois944
Copy link

@farhazulMullick
Hi,
On Android, you are correct, it's the NavBackStatckEntry who manage the lifecycle as it was made for it. Koin do the same thing as Hilt, no big issue here.
On iOS, it's the SwiftUI @StateObject + ObservableObject who are in charge to manage the lifecycle, just like the SwiftUI ViewModel.

On iOS, Koin can't manage the lifecycle of the KMP ViewModel.

Take a look at my playground, it should be inspiring.

@ArcherEmiya05
Copy link

ArcherEmiya05 commented Aug 16, 2024

Is my understanding here is correct that ViewModel 2.8.x still not working with Koin? I tried Koin 4.0.0-RC1 and ViewModel 2.8.4 after moving the declaration of viewModelOf (now located in org.koin.core.module.dsl.viewModelOf) from app module to shared module I am getting runtime error below.

java.lang.RuntimeException: Unable to start activity Could not create instance for '[Factory:'com.sample.app.presentation.viewmodels.SampleViewModel']'

I am working with View base project migrating to KMM.

androidApp

class App : Application() {

    override fun onCreate() {
        super.onCreate()

        initKoin {
            androidContext(this@App)
            modules(androidCommonModule, appModule)
        }
        
}

shared

fun initKoin(config: KoinAppDeclaration = {}) {

    startKoin {
        config()
        modules(
            commonModule,
            sharedModule
        )
    }

}

SharedModule.kt
expect val sharedModule: Module

SharedModule.android.kt

actual val sharedModule = module {

    single {
        Room
            .databaseBuilder<AppLocalDatabase>(
                context = androidApplication(),
                name = androidApplication().getDatabasePath("cryptonian.db").absolutePath
            )
            .addTypeConverter(get<SampleTypeConverter>())
            .fallbackToDestructiveMigration(true)
            .build()
    }

    single {
        get<AppLocalDatabase>().sampleDao
    }

    viewModelOf(::SampleViewModel)

}

SharedModule.ios.kt

actual val sharedModule = module {

    single {
        Room
            .databaseBuilder<AppLocalDatabase>(
                name = NSHomeDirectory() + "/cryptonian.db"
            )
            .addTypeConverter(get<SampleTypeConverter>())
            .fallbackToDestructiveMigration(true)
            .build()
    }

    single {
        get<AppLocalDatabase>().sampleDao
    }

    singleOf(::SampleViewModel)

}

It is pointing in one of my Fragment that do field injection.

val viewModel by viewModel<SampleViewModel>()

@frankois944
Copy link

frankois944 commented Aug 16, 2024

Is my understanding here is correct that ViewModel 2.8.x still not working with Koin? I tried Koin 4.0.0-RC1 and ViewModel 2.8.4 after moving the declaration of viewModelOf (now located in org.koin.core.module.dsl.viewModelOf) from app module to shared module I am getting runtime error below.

java.lang.RuntimeException: Unable to start activity Could not create instance for '[Factory:'com.sample.app.presentation.viewmodels.SampleViewModel']'

I am working with View base project migrating to KMM.

androidApp

class App : Application() {

    override fun onCreate() {
        super.onCreate()

        initKoin {
            androidContext(this@App)
            modules(androidCommonModule, appModule)
        }
        
}

shared

fun initKoin(config: KoinAppDeclaration = {}) {

    startKoin {
        config()
        modules(
            commonModule,
            sharedModule
        )
    }

}

SharedModule.kt expect val sharedModule: Module

SharedModule.android.kt

actual val sharedModule = module {

    single {
        Room
            .databaseBuilder<AppLocalDatabase>(
                context = androidApplication(),
                name = androidApplication().getDatabasePath("cryptonian.db").absolutePath
            )
            .addTypeConverter(get<SampleTypeConverter>())
            .fallbackToDestructiveMigration(true)
            .build()
    }

    single {
        get<AppLocalDatabase>().sampleDao
    }

    viewModelOf(::SampleViewModel)

}

SharedModule.ios.kt

actual val sharedModule = module {

    single {
        Room
            .databaseBuilder<AppLocalDatabase>(
                name = NSHomeDirectory() + "/cryptonian.db"
            )
            .addTypeConverter(get<SampleTypeConverter>())
            .fallbackToDestructiveMigration(true)
            .build()
    }

    single {
        get<AppLocalDatabase>().sampleDao
    }

    singleOf(::SampleViewModel)

}

It is pointing in one of my Fragment that do field injection.

val viewModel by viewModel<SampleViewModel>()

Give us the full stack of the error, the real reason is not at the top, the somewhere down there.

The Koin binding error reason are not at the top of the stack.

@ArcherEmiya05
Copy link

Give us the full stack of the error, the real reason is not at the top, the somewhere down there.

The Koin binding error reason are not at the top of the stack.

Yes the error at top is usually not the actual cause, however in my case these are the only logs after crash.

FATAL EXCEPTION: main
                 Process: com.sample.app, PID: 2871
                 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.app/com.sample.app.presentation.MainActivity}: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                 	at android.app.ActivityThread.access$800(ActivityThread.java:144)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                 	at android.os.Handler.dispatchMessage(Handler.java:102)
                 	at android.os.Looper.loop(Looper.java:135)
                 	at android.app.ActivityThread.main(ActivityThread.java:5221)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at java.lang.reflect.Method.invoke(Method.java:372)
                 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                 Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:57)
                 	at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
                 	at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:109)
                 	at org.koin.core.scope.Scope.resolveValue(Scope.kt:247)
                 	at org.koin.core.scope.Scope.resolveInstance(Scope.kt:233)
                 	at org.koin.core.scope.Scope.get(Scope.kt:212)
                 	at org.koin.viewmodel.factory.KoinViewModelFactory.create(KoinViewModelFactory.kt:24)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:65)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.kt:47)
                 	at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:91)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel(GetViewModel.kt:45)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel$default(GetViewModel.kt:29)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:83)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:49)
                 	at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.getViewModel(AssetsFragment.kt:122)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.subscribeUI(AssetsFragment.kt:218)
                 	at com.devsbitwise.android.common.presentation.ui.fragment.BaseFragment.onViewCreated(BaseFragment.kt:131)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3152)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3170)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3153)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.Fragm
12:58:14.516  D  ERR: exClass=java.lang.ClassNotFoundException
12:58:14.516  D  ERR: exMsg=Didn't find class "com.devsbitwise.kmm.shared.data.data_source.local.AppLocalDatabase_Impl" on path: DexPathList[[zip file "/data/app/com.sample.app-2/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
12:58:14.516  D  ERR: file=BaseDexClassLoader.java
12:58:14.516  D  ERR: class=dalvik.system.BaseDexClassLoader
12:58:14.516  D  ERR: method=findClass line=56
12:58:14.516  D  ERR: stack=java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.app/com.sample.app.presentation.MainActivity}: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                 	at android.app.ActivityThread.access$800(ActivityThread.java:144)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                 	at android.os.Handler.dispatchMessage(Handler.java:102)
                 	at android.os.Looper.loop(Looper.java:135)
                 	at android.app.ActivityThread.main(ActivityThread.java:5221)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at java.lang.reflect.Method.invoke(Method.java:372)
                 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                 Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:57)
                 	at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
                 	at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:109)
                 	at org.koin.core.scope.Scope.resolveValue(Scope.kt:247)
                 	at org.koin.core.scope.Scope.resolveInstance(Scope.kt:233)
                 	at org.koin.core.scope.Scope.get(Scope.kt:212)
                 	at org.koin.viewmodel.factory.KoinViewModelFactory.create(KoinViewModelFactory.kt:24)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:65)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.kt:47)
                 	at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:91)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel(GetViewModel.kt:45)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel$default(GetViewModel.kt:29)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:83)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:49)
                 	at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.getViewModel(AssetsFragment.kt:122)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.subscribeUI(AssetsFragment.kt:218)
                 	at com.devsbitwise.android.common.presentation.ui.fragment.BaseFragment.onViewCreated(BaseFragment.kt:131)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3152)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3170)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3153)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at andro
12:58:14.516  D  ERR: TOTAL BYTES WRITTEN: 26552

@ArcherEmiya05
Copy link

Give us the full stack of the error, the real reason is not at the top, the somewhere down there.
The Koin binding error reason are not at the top of the stack.

Yes the error at top is usually not the actual cause, however in my case these are the only logs after crash.

FATAL EXCEPTION: main
                 Process: com.sample.app, PID: 2871
                 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.app/com.sample.app.presentation.MainActivity}: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                 	at android.app.ActivityThread.access$800(ActivityThread.java:144)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                 	at android.os.Handler.dispatchMessage(Handler.java:102)
                 	at android.os.Looper.loop(Looper.java:135)
                 	at android.app.ActivityThread.main(ActivityThread.java:5221)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at java.lang.reflect.Method.invoke(Method.java:372)
                 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                 Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:57)
                 	at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
                 	at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:109)
                 	at org.koin.core.scope.Scope.resolveValue(Scope.kt:247)
                 	at org.koin.core.scope.Scope.resolveInstance(Scope.kt:233)
                 	at org.koin.core.scope.Scope.get(Scope.kt:212)
                 	at org.koin.viewmodel.factory.KoinViewModelFactory.create(KoinViewModelFactory.kt:24)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:65)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.kt:47)
                 	at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:91)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel(GetViewModel.kt:45)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel$default(GetViewModel.kt:29)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:83)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:49)
                 	at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.getViewModel(AssetsFragment.kt:122)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.subscribeUI(AssetsFragment.kt:218)
                 	at com.devsbitwise.android.common.presentation.ui.fragment.BaseFragment.onViewCreated(BaseFragment.kt:131)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3152)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3170)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3153)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.Fragm
12:58:14.516  D  ERR: exClass=java.lang.ClassNotFoundException
12:58:14.516  D  ERR: exMsg=Didn't find class "com.devsbitwise.kmm.shared.data.data_source.local.AppLocalDatabase_Impl" on path: DexPathList[[zip file "/data/app/com.sample.app-2/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
12:58:14.516  D  ERR: file=BaseDexClassLoader.java
12:58:14.516  D  ERR: class=dalvik.system.BaseDexClassLoader
12:58:14.516  D  ERR: method=findClass line=56
12:58:14.516  D  ERR: stack=java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.app/com.sample.app.presentation.MainActivity}: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                 	at android.app.ActivityThread.access$800(ActivityThread.java:144)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                 	at android.os.Handler.dispatchMessage(Handler.java:102)
                 	at android.os.Looper.loop(Looper.java:135)
                 	at android.app.ActivityThread.main(ActivityThread.java:5221)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at java.lang.reflect.Method.invoke(Method.java:372)
                 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                 Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for '[Factory:'com.sample.module.presentation.viewmodels.SampleAssetViewModel']'
                 	at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:57)
                 	at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
                 	at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:109)
                 	at org.koin.core.scope.Scope.resolveValue(Scope.kt:247)
                 	at org.koin.core.scope.Scope.resolveInstance(Scope.kt:233)
                 	at org.koin.core.scope.Scope.get(Scope.kt:212)
                 	at org.koin.viewmodel.factory.KoinViewModelFactory.create(KoinViewModelFactory.kt:24)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:65)
                 	at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.kt:47)
                 	at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:91)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel(GetViewModel.kt:45)
                 	at org.koin.viewmodel.GetViewModelKt.resolveViewModel$default(GetViewModel.kt:29)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:83)
                 	at com.sample.app.presentation.ui.main.AssetsFragment$special$$inlined$viewModel$default$2.invoke(FragmentVM.kt:49)
                 	at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.getViewModel(AssetsFragment.kt:122)
                 	at com.sample.app.presentation.ui.main.AssetsFragment.subscribeUI(AssetsFragment.kt:218)
                 	at com.devsbitwise.android.common.presentation.ui.fragment.BaseFragment.onViewCreated(BaseFragment.kt:131)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3152)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3170)
                 	at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3153)
                 	at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:608)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:286)
                 	at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
                 	at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1675)
                 	at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3259)
                 	at andro
12:58:14.516  D  ERR: TOTAL BYTES WRITTEN: 26552

Never mind I found the issue from this log Didn't find class "com.devsbitwise.kmm.shared.data.data_source.local.AppLocalDatabase_Impl" , it seems KSP for Room should be implemented in shared module as well where the abstract class database is located.

@arnaudgiuliani
Copy link
Member

following checks on KMP. But seems ok

@arnaudgiuliani
Copy link
Member

To follow on RC2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests