guerdaa
guerdaa

Reputation: 216

Multiple ViewModels for a single compose function (Screen)

I am building an app like Gmail with compose. In portrait mode, it only shows the list messages as the main screen of the app, and when the user clicks on one message, the app will navigate to message detail screen. Both screens have a ViewModel: MessagesListViewModel and MessageDetailViewModel.

In landscape mode, I want to show both screens at once, next to each other: on the left side, messages list screen and on the right side, message detail screen of the selected message.

My solution to do that, is that I create a route for message list screen to handle different cases:

So basically I have a compose function that handles all this cases. My question here, is it a good practice to have multiple view models in this compose function?

Upvotes: 1

Views: 5554

Answers (2)

Gastón Saillén
Gastón Saillén

Reputation: 13129

There is a much better solution for this, with just 1 viewmodel that emits the uiStates you need, for example

For Portrait (no message opened) you can emit a uiState with just the message list

For Portrait (message opened) you can emit a uiState with just the message details

For Landscape (show both) you can emit a uiState with message details + selected message (to select in the list) + the message list

Since you did not provided any code, I did a little drawing of what I mean, you can just emit the data from the ViewModel, then observe it in your Activity / Fragment and then propagate and open the right composable depending on the uiState.

You can contain these 3 composables inside 1 but for that you will need to send the 3 uiStates to that composable and with a when statment decide which composable to open.

I think separating these screen like this will make it much cleaner, also you don't need more than 1 viewModel.

enter image description here

as per @fstanis answer, is it like that, there is no right answer, it depends on what architecture you want to follow and how you want to do it.

From what you describe you can do it both ways

Having 1 ViewModel for everything (take care that it could have more code than separating these into different ViewModels)

Benefits

  • You contain all these 3 screens into 1 ViewModel
  • No more instances for any new viewmodel
  • You can share data/communicate between these 3 screens with this one ViewModel

Cons

  • It could bloat your ViewModel with a lot of code (depending on your case)

The other way is to have 1 ViewModel per composable, that can separate the logic, but it depends if you need to communicate data between them, if you need to communicate, you will need to send arguments between the navigation of each screen and live the ViewModels in the respective composable

Upvotes: 5

fstanis
fstanis

Reputation: 5534

There's unlikely to be one right answer here, but per State holders and UI State:

Note: You should only use ViewModel with destination-level UIs. You shouldn't use them in reusable pieces of your UI, such as search bars or Chip groups. In these cases plain classes are better suited.

It sounds like you have a single destination-level UI here which has a different appearance depending on the configuration (landscape / portrait). Therefore, it sounds like a single ViewModel would be more in line with the current guidelines.

Upvotes: 2

Related Questions