One Off the Slack: How Do We Have ViewModels Scoped to a Composable?
Tiago Araujo asked:
Is there already a way to scope view models by composable?
Google’s Adam Powell indicated that it was possible but wanted more details, so Tiago continued:
Let’s say I’ve a pager with the same composable and each needs their own instance of the same viewmodel. How would I do that?
Adam responded:
have each of your pages provide
LocalViewModelStoreOwnerand multiplex them into a host viewmodel; this is how androidx navigation-compose does it
you’ll have some decisions to make around the intended lifecycle of those viewmodels, how long to keep them alive and when to clear them if you don’t keep all of the pager’s pages composed at the same time
Later in the thread, Marco Romano had a bit of a “wait, wut?” moment around the phrase “multiplex them into a host viewmodel”, so Adam explained:
my apologies; you have a point where you need to create one
ViewModelStoreper page, each one establishes a namespace and scope for viewmodels obtained beneath it. You need a place to store thoseViewModelStores and make sure they’re retained. Using anotherViewModelis the most straightforward way to do this since it already provides all of the facilities and guarantees you want. You’ll create your ownViewModelthat stores a map of some key that is unique for each page to aViewModelStore, and you’ll need to manage the addition and removal of theseViewModelStores from that map. Then you’ll need to provide the correctViewModelStoreviaLocalViewModelStoreOwnerto the content of each page.
Tiago asked:
so it requires some work I see, I’ll have to create some custom implementation of
LocalViewModelStoreOwnerright? I need to check how the navigation does it then
Adam elaborated:
a little work, but not too much. the usual way to think about this is to have the composable function that provides the
LocalViewModelStoreOwnerfetch a container ViewModel that you write for this purpose. Then use aRememberObserverto remove+clear theViewModelStorewhen a page leaves the composition if the host activityisChangingConfigurationisn’ttrue
(since if you’re tearing down the composition for a config change you want to leave them alone)
the reason to use
RememberObserverdirectly instead ofDisposableEffectis because you need to hookonAbandonedtoo; ViewModels are created during composition and need to be cleaned up if the composition they were created in doesn’t commit
shouldn’t be more than ~70-100 lines of utility code that you write once and don’t have to look at again 🙂
Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!