How to use multiple mutableState in one compose screen

137 Views Asked by At

I have three api in ViewModel that are below.

  1. API for UserList
  2. API for DeviceList
  3. API for EventList

All api have three state (Loading, Success, Error)

I have to show all three info on Dashboard.

What is best way to call and listen this api response.

Should I collect three different state for every api call or combine all api state in single class and collect this.

I tried three different state for every api.

But problems is that I have to handle Loading, Success, Error state for every api.

Every time state change called when another api state change and screen recompose multiple time.

2

There are 2 best solutions below

0
Leviathan On

It won't really matter if properly implemented.

A recompose will have to occur no matter what, since you want the changed data to be displayed. The compose framework will, however, only touch the data that actually changed. If you have a large, unified ui state object, only the parts of data that have structurally changed (just compared with !=, no referential inequality with !== needed) will trigger a recompose for the composables that actually need the data. And a lot of composables will just route data through to their children, so recomposing them is very cheap.

So there is no need to be afraid of recompositions, you just have to make sure that your composables are lean and only do what they necessarily need to do. Expensive calculations should be remembered or delegated to the viewmodel.

Then, there is the viewmodel. Your APIs should be delivering their data as flows so that the viewmodel just needs to perform some transformations on those flows. The idea is to never collect the flows in the viewmodel, this will only be done by the composables that retrieve your viewmodel's ui state as a StateFlow (preferably with collectAsStateWithLifecycle()).

Since your ui state should consist of simple, immutable data classes, the state can easily be updated during your flow transformations. The flows will provide the same objects for data that hasn't changed, so creating new instances of data classes to hold that data will reuse these objects. That is also pretty cheap performance and memory wise.

If you follow best practices using a clean architecture, it won't matter much if you distribute your state over multiple objects or have one monolithic state object. The deciding factor should rather be the clarity of your code. Having to many scattered state objects will make the code harder to piece together, while having one convoluted state object can make it hard to understand where what data can be found.

0
Philio On

It really depends how you want to present the data.

If your screen consists of 3 completely separate sections, each section representing the data from a single API:

  • Create a composable for each section
  • Create a view model for each composable
  • Add logic to call the relevant API in each view model and propagate the state to the UI
  • Handle state updates in each composable

If the data from one API is refreshed, only one composable will need to recompose.

If you are combining the data in some way then you should do this outside of the UI layer:

  • Create a domain model which represents the combined data
  • Call the relevant APIs, combine the data, map to the domain model
  • Update the UI with a single state change