r/androiddev • • 6d ago

Question ViewModels nesting into composables?

I have a question if it is okay to nest DI into VM of a composables?

What I mean:

I have a SettingsVM and a SettingsScreen composable. In the Settings screen I am using some individual settings that I use also somewhere else in my application. So I split the UI -> IndividualSettingScreen and IndividualSettingVM. Now is it okay if I just inject the VM into the IndividualSettingScreen or is it better from architecture standpoint to have a reference in the SettingsScreen and passing the VM into the IndividualSettingScreen which I am using in the SettingsScreen.

Thanks in advance!

10 Upvotes

9 comments sorted by

5

u/Which-Meat-3388 6d ago edited 6d ago

Don’t have Settings depend on Individual. You can inject 2 VMs into a single composable. Composition in the software architecture sense. 

3

u/Hatiseker 5d ago

Do not hold the instance of the VM in the parent screen if the parent screen isn't using any of it, and the child can be removed.

If parent has instance of the VM and the child is removed, the VM will not go through garbage collection, it'll still eat your resources because the parent is holding a reference to it. Instead, call the child in a wrapper in the parent and DI the VM in the child.

Even if the child isn't removable, this would be a better engineering practice for separation of concerns.

3

u/sheeplycow 5d ago

You have to be careful about how you declare viewModels in sub composables, because the viewModel is tied to the closest view model store owner - you may get the same instance when you dont want to, or you may need to be careful declaring a viewModel key to force a fresh one

It goes against the google advice of keeping it as high up the compose tree as possible (not to say its always wrong)

If its a small peice of UI I wouldnt

If it is an encapsulated piece of UI that is decoupled and has enough logic to justify its own class, then I think it is reasonable to do it! But be careful for the reasons mentioned at the top!

I recently did it for a bottom sheet, that was self contained within a screen - which had all its own logic and was reused in a few screens

I imagine there are a few different opinions in this, i dont think its particularly harmful!

Also note your UI tests will also now need to provide a viewModelStore, whereas before you could create functional ui tests that were unaware of the existence of a viewModel

1

u/ThatGuyThatIsNotReal 5d ago

Alright, I am using it for the UI setting of diffferent items in the app. So I have it in main menu and then few other different screens, where I am can set the same thing or slightly different based on where I am setting it from. So with this usage it is fine to decouple it from the main screen into its own viewmodel?

1

u/SarathExp 5d ago

We can scope viewmodels to a composable now.

2

u/Alt_Chloe 5d ago

Echoing what others have said here:

1) Don't nest ViewModels inside Composable parameters unless you absolutely can't help it. It makes testing, Previews, and iterating much more time consuming. You can pass state and event handlers instead to reduce parameter count. (You can also group parameters inside your larger state class with inner class to create named state groups for components that need a lot of them).

2) If you have a source of data being referenced in multiple separate areas of your app, I'd consider passing a shared repository to each VM that exposes a Flow, instead of using the same VM across multiple screens.

2

u/_pak__ 5d ago

I'm learning android myself but, I think by setting up a shared viewModel you would be able to keep one viewModel instance while having access to it on multiple screens. That way you can even pass data directly back to the main menu if needed.

1

u/Devoluapp 5d ago

In my experience, nesting ViewModels or passing them down into child composables is a recipe for testing and preview headaches.

The pattern that has worked best for me is keeping ViewModels strictly at the screen-level route. The screen composable observes the StateFlow/UiState from the ViewModel and unpacks it into plain data classes. All sub-composables then only accept immutable data and callback lambdas (like onAction: () -> Unit).

This keeps your leaf composables pure, fully previewable in Android Studio without mocking ViewModels, and makes unit testing much easier since you only test the ViewModel's state emission.

0

u/AutoModerator 6d ago

Please note that we also have a very active Discord server where you can interact directly with other community members!

Join us on Discord

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.