Is it bad practice to pass viewmodels to child composables in jetpack compose?

Viewed 316

Example:

I have a @Composable func WorkoutScreen(...) which injects a dedicated ViewModel (e.g. with hilt). It displays some different child composables like @Composable func ProgressView(...) and some others. ProgressView is the only composable in the whole screen, which observes/needs a specific State property x from the injected ViewModel. Would it be bad practice to pass the ViewModel from WorkoutScreen as parameter down to ProgressView? Or should I just pass the States value only?

Let's think this further and say I pass only the State. Also let's say, not ProgressView is the one needing the State, but just another child of ProgressView. If the State changes now, the whole ProgressView might be recompositioned since "its input changes" (instead of just the child), if I understood correctly. Wouldn't this lead to unnecessary recomps?

2 Answers

The entire Composable shouldn't recompose, since Compose is efficient enough to recompose only the Composable which are explicitly reading a state.

Don't worry about efficiency, it won't get affected. For the principles part, no, you shouldn't pass the model around. That is because of the separation-of-concerns principle. All the parts of the program should have access to only as much information as they need to function - no more, no less.

If you pass the entire viewmodel around, firstly every part of the app will have access to everything inside the viewmodel, and may modify properties leading to conflicts. It also makes the viewmodel tightly coupled with a lot of Composable code, whereas passing only the state, limits the coupling to only the part of the viewmodel that is actually required by the Composable. Finally y, if you pass the viewmodel around, it would be practically impossible to test your apps, since you'll need to generate a whole new "fake" viewmodel, with fake values for testi, which will become problematic as the model grows more and complex.

Use state-hoisting. Read here: https://developer.android.com/codelabs//jetpack-compose-state#8, or another stack overflow answer

Passing a ViewModel to a child composable is not very good practice. Only Screen-Level Composables (Main UI Page) should access ViewModel business logic. There are two main benefits of this approach:

  1. Your child's composable will become reusable.

  2. There is no concrete implementation, So you can easily update the

    business logic.

Related