Nojipiz
Nojipiz

Reputation: 63

Is there a way to maintain MVI pattern and still prevent excessive state updates in a Jetpack Compose-based Android project using Orbit MVI?

I'm new to MVI architecture in Android development, i'm using Orbit MVI and Jetpack compose for my new project.

Of course, with MVI there is only one state for the entire view and everything will be updated if the state changes, according to the docs:


@Composable
fun SomeScreen(viewModel: SomeViewModel) {
  val state by viewModel.collectAsState()
  
  viewModel.collectSideEffect {
    when(it) {
      ...
    }
  }

  SomeContent(
    state = state
  )
}

Now in my state i have the following elements and the composables to render them:

data class State(
  val element: List<MyObject> // A medium LIST (+100) of my custom objects
  val fieldText: String // Textfield in the sameview
)

After the list load at the first time everything is ok, the performance of my view is good because the state is´t updating. BUT when i start to change my fieldText, my state will update the state EVERY TIME the textfield changes (one time per character of course) and my view becomes extremely laggy.

I understand that the problem is the rendering of the lazycolumn, even if the list isn´t changing, the state is changing so the view renders the lazycolumn again.

The easy way to solve this is implementing multiple states in the view model, but this will "break" the MVI pattern, i need something that gives me granular control over the state.

Upvotes: 2

Views: 1239

Answers (1)

jassycliq
jassycliq

Reputation: 46

Sounds like your issue is that collections are always considered unstable by the Compose compiler.

“Collection classes like List, Set and Map are always determined unstable as it is not guaranteed they are immutable. You can use Kotlinx immutable collections instead or annotate your classes as @Immutable or @Stable.” — Ben Trengrove https://link.medium.com/JqhPKxeRfBb

There are a couple of solutions highlighted in that medium article but it comes down to either:

  • use Kotlinx Immutable Collections
  • wrap the list in class marked as immutable/stable and use that wrapper class in your State class

Upvotes: 2

Related Questions