Sahil Arora
Sahil Arora

Reputation: 492

How to share same instance of ViewModel between Activities using Koin DI?

I am using Koin library in Kotlin for DI

Koin providing by viewmodel() for get instance of ViewModel by sharedViewModel() to get same instance in fragments.

How can I get same instance of the ViewModel in activities ? I didn't find any way to achieve this.

Upvotes: 19

Views: 23263

Answers (4)

Ekenne Chilex
Ekenne Chilex

Reputation: 41

I know this is very very late but you can try this: if you are extending a baseviewmodel, you need to declare the baseViewmodel as a single then in your respective activity inject the BaseViewModel. Practical example:

val dataModule = module {
    single { BaseViewModel(get(), get()) }
}

in your ViewModel

class LoginViewModel(private val param: Repository,
                            param1: Pref,
                            param2: Engine) : BaseViewModel(param1, param2)

Then in your activity class

val baseViewModel: BaseViewModel by inject()

Hope this help someone.

Upvotes: -2

Catalin
Catalin

Reputation: 159

I would suggest making the app a ViewModelStoreOwner and injecting the viewModels using as owner the app. The code required would look like this

class App : Application(), ViewModelStoreOwner {
    private val mViewModelStore = ViewModelStore()

    override fun getViewModelStore(): ViewModelStore {
        return mViewModelStore
    }
}

You can define some extensions to easily inject the viewModels


val Context.app: App
    get() = applicationContext as App

inline fun <reified T : ViewModel> Context.appViewModel(
    qualifier: Qualifier? = null,
    noinline state: BundleDefinition? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> {
    return lazy(LazyThreadSafetyMode.NONE) {
        GlobalContext.get().getViewModel(qualifier, state, { ViewModelOwner.from(app, null) }, T::class, parameters)
    }
}

inline fun <reified T : ViewModel> Fragment.appViewModel(
    qualifier: Qualifier? = null,
    noinline state: BundleDefinition? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> {
    return lazy(LazyThreadSafetyMode.NONE) {
        GlobalContext.get().getViewModel(qualifier, state, { ViewModelOwner.from(requireContext().app, null) }, T::class, parameters)
    }
}

You can then inject your viewModel like this

class MainActivity : AppCompatActivity() {
    private val mAppViewModel: AppViewModel by appViewModel()
}

The advantage of this solution is that you don't need to recreate the view model and if you decide to save the state between app restarts, you can easily make the app an SavedStateRegistryOwner as well and using the SavedStateHandle save/restore your state from inside the viewModel, being now bound to the process lifecycle.

Upvotes: 4

Sahil Arora
Sahil Arora

Reputation: 492

After some research or discussion on architecture level and also report and issue github Koin,i found solution for this In this scenario,We should save that state/data into Repository which we need to share between multiple activities not in the viewModel and two or more different ViewModels can access same state/data that are saved in single instance of repository

see here

Upvotes: 7

Hayk Melkonyan
Hayk Melkonyan

Reputation: 2150

you need to read more about ViewModel to understand it better. https://developer.android.com/topic/libraries/architecture/viewmodel

ViewModel is connected to your Activity

so you can share your Activities ViewModel only between his Fragments ,

that is what mean sharedViewModel in koin

sharedViewModel is the same if you use ViewModel Factory with same context .

sharing any data between Activities can be done via Intent , there is no another way in Android,

or you can keep some static / global data and share it between Activities

Upvotes: 2

Related Questions