A Compose state of mind: Using Jetpack Compose's automatic state observation
了解 Compose 的状态模型和 Composition,何时提升状态并创建状态容器或使用 AAC ViewModel,以及如何在 Composition 之外安全地改变状态以便 Compose 跟踪这些更改。
SEARCH 页面: 
从 SEARCH 页面切换到 MY CART 页面: 
State changes need to be tracked by Compose.
状态变化需要被 Compose 跟踪。

Use Compose's State and MutableState types to make state observable.
使用 Compose 的 State 和 MutableState 类型来使状态可被观察。

State created in composables needs to be remembered.
在可组合项中创建的状态需要被记住。

In this way, the state will be part of the composition and will be reused when the function recomposes.
这样,状态将成为组合的一部分,并在函数重组时被重新使用。

RememberSaveable
State survives configuration changes.
State 能经受配置变更。
rememberSaveable 适用于界面状态,比如商品数量或选定的标签页,但不适用于过渡动画状态等。

Property delegate

Mutating state
State is always mutated outside the scope of a composable function.
你应该只在可组合函数的作用域之外改变状态,因为可组合项可以频繁运行并以任何顺序执行。


Resuable Composable

如果 Composable 不持有特定的状态,那么其内部就不应该有更新状态的逻辑,应该通知调用方去更新。

State hoisting
状态提升是一种将不公开状态移出可组合项的模式,使可组合项更趋于无状态,从而提高在应用中的可重用性。
无状态可组合项是指:不保存任何不公开状态的可组合项。

可组合项应接收状态作为参数并使用 lambda 向上传递事件,这样可以提高可组合项的可重用性和可测试性。




Hoist state to at least the lowest common ancestor of its consumers.
至少应将状态提升到需要访问该状态的可组合项的最低公共父项。
Composable parameters: pass only what they need.
可组合项应该只接受需要的参数。


Stateful and stateless composables
有状态和无状态可组合。

Managing state - Defining source of truth
状态管理

-
可组合项用于管理简单的界面元素状态
-
状态容器用于管理复杂的界面元素状态
-
架构组件 ViewModel 是一种特殊的状态容器类型,用于提供对业务逻辑的访问并准备要呈现的应用数据。
Types of state and logic

-
界面元素状态是指界面元素的提升状态,例如,ScaffoldState。
-
屏幕或界面状态是指需要在屏幕上显示的内容,要显示在屏幕上,例如,CartUiState 可以包含 CartItem,向用户显示的消息或加载标志,此类状态通常与层次结构中的其他层相关联,因为它包含应用数据。
-
界面行为逻辑与如何在屏幕上显示状态更改相关,屏幕上的状态变化,例如,导航逻辑或显示信息提示控件,界面行为逻辑应始终位于组合中。
-
业务逻辑决定着如何处理状态更改,例如,如何付款或存储用户偏好设置,这种逻辑通常位于业务层或数据层,但绝不会位于界面层。
Composables as source of truth
如果要处理的界面元素状态比较简单,可以放在可组合项本身中。
在本例中,JetsnackApp()可组合项持有 scaffoldState,由于 scaffoldState 包含可变属性,因此,与它相关的所有交互都应该在这个可组合项中进行。否则,如果将它传递给其他可组合项,这些可组合项可能会改变它的状态,这不符合单一可信来源原则,而且会使 bug 跟踪变得更加困难。

State holders as source of truth
但是,实际情况会更加复杂: 
根据分离关注点原则,我们可以将界面逻辑和界面元素状态,委托给称为"状态容器"的另一个类,并保留可组合函数,并让可组合函数只负责发出界面元素。JetsnackAppState 将是 JetsnackApp 的界面元素状态的可信来源。因此所有状态写入都应在该类中进行。 
State holders as source of truth

State holders 还可以包含在更改时引发重新组合的组合项属性。 

Remembered state holder

Using the state holder

简而言之,状态容器是一个普通类,用于提升界面元素的状态,并包含界面相关的逻辑。
状态容器可以降低可组合项的复杂性并提高可测试性。
它还使状态提升变得更容易,因为只需提升一个状态,而不是多个状态。

Search state holder
状态容器可以非常简单并只用于特定用途,例如,这个 SearchState 类用于搜索屏幕,仅包含 activeFilters 和 searchResults 列表结果。

ViewModels as source of truth

ViewModel 有两项用途,首先,提供对应用的业务逻辑的访问,其次,准备要在特定屏幕上呈现的应用数据用于在特定屏幕上进行演示。

ViewModel 不属于组合的一部分,因此不能接受组合作用域内的状态。


但在本例中,由于 uiState 位于组合之外,因此不需要记住它,只需使用它,该函数将在 uiState 更改时重新执行。

Streams of data in Compose?

Integration with reactive streams

总的来说,ViewModel 可以将状态提升到组合之外并具有更长的生命周期。ViewModel 负责屏幕的业务逻辑决定要显示哪些数据,从其他层获取数据并对这些数据进行呈现前的准备用于演示。
因此,建议在屏幕级可组合项中使用 ViewModel。


ViewModels and State holders



Resources
