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

huangapple go评论61阅读模式
英文:

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 isn'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.

英文:

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&lt;MyObject&gt; // 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.

答案1

得分: 0

"听起来你的问题是,Compose编译器总是认为集合是不稳定的。"
">“像List、Set和Map这样的集合类总是被视为不稳定的,因为不能保证它们是不可变的。您可以使用Kotlinx不可变集合,或者将您的类标记为@Immutable或@Stable。”— Ben Trengrove https://link.medium.com/JqhPKxeRfBb"
"在那篇中等文章中,提到了一些解决方案,但归根结底有两种选择:"
"- 使用Kotlinx不可变集合"
"- 将列表包装在标记为不可变/稳定的类中,并在您的State类中使用该包装类。"

英文:

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

huangapple
  • 本文由 发表于 2023年5月20日 21:14:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295415.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定