https://kotlinlang.org logo
#koin
Title
# koin
l

Lukasz Kalnik

08/12/2022, 12:42 PM
I would be also interested in sharing the same ViewModel instance between a composable (or multiple composables) and host Fragment/Activity. My use case is that I have click callbacks in the composables which trigger events in the viewmodel. Then host Fragment subscribes to this event to show snackbar or trigger navigation.
m

Moritz Post

08/23/2022, 9:28 AM
You could create a custom Scope and pass in a "session" object so that each view model gets the same instance
l

Lukasz Kalnik

08/23/2022, 9:30 AM
But then every time I navigate away I would have to destroy the scope.
m

Moritz Post

08/23/2022, 9:30 AM
The scope can be given to each view model
l

Lukasz Kalnik

08/23/2022, 9:31 AM
Yes, but I want to have a new viewmodel once I navigate to the same screen with new data
m

Moritz Post

08/23/2022, 9:31 AM
That would mean you create a new "session".
eg if you have screens like A -> B -> C you would create a new shard "session" object when starting A and pass that shared object to B and C
l

Lukasz Kalnik

08/23/2022, 9:32 AM
So then I would need to create/destroy the session as part of my navigation, right?
m

Moritz Post

08/23/2022, 9:32 AM
Actually not as part of the navigation but automatically in your koin module declaration
l

Lukasz Kalnik

08/23/2022, 9:34 AM
So I just have to do
getKoin().createScope()
? But when will the session be finished? Will it be automatically finished when I leave the starting fragment?
m

Moritz Post

08/23/2022, 9:36 AM
In that case that would be up to the screen/ViewModel that the session is tied to
Example:
l

Lukasz Kalnik

08/23/2022, 9:37 AM
Ok, that sounds like a good idea to try out.
m

Moritz Post

08/23/2022, 9:37 AM
you create a module with a Session
Copy code
private val myModule = module {
        scope<Session> {
            scoped { MySession() }
        }
    }
and another which would create your ViewModels:
Copy code
private var mySessionScope: Scope? = null
    private val viewModelModule = module {
        viewModel {
            mySessionScope = getKoin().createScope<Session>()
            with(requireNotNull(mySessionScope)) {
                ScreenAViewModel(get(), get()).apply {
                    addCloseable { close() }
                }
            }
        }
        viewModel {
            with(requireNotNull(mySessionScope)) {
                ScreenBViewModel(get())
            }
        }
        viewModel {
            with(requireNotNull(mySessionScope)) {
                ScreenCViewModel(get())
            }
        }
    }
Here you can saee that ScreenA is used to close the mySessionScope scope
the
get()
calls would be able to resolve the shared
MySession
.
l

Lukasz Kalnik

08/23/2022, 9:41 AM
Interesting, I didn't see that
addCloseable
before...
m

Moritz Post

08/23/2022, 9:41 AM
That is from androidx.lifecycle.ViewModel
it would than be able to close the session
The solution is not 100% nice because the sessionScope is held in a separate var instead of getting from the koin object each time.
l

Lukasz Kalnik

08/23/2022, 9:43 AM
I see, that's new in 2.5.0
Thanks for your suggestions, do you know any resource/article which goes in more depth into scoped viewmodels in Koin? I find that the documentation is missing some of the more specific use cases.
m

Moritz Post

08/23/2022, 9:45 AM
yeah i agree. i pieced it together from the docs and various repos i think.
no immediate pointers
l

Lukasz Kalnik

08/23/2022, 9:45 AM
Ok, thanks so much for your help, this is really cool!
m

Moritz Post

08/23/2022, 9:45 AM
you are welcome. Good Luck.
123 Views