这更多的是对flutter Riverpod状态管理包的理论探讨。目前,我正在尝试将一个大型项目从 Provider 迁移到 Riverpod,我遇到了一个问题,该问题在 Provider 中很容易解决,但似乎是 Riverpod 的“阻碍”。
所以问题如下。
想象一下,您有一个可以从应用程序的多个位置打开的 ClientDetailScreen。到达那里的基本路径是“ClientsTab”>“搜索”(单击搜索的名称)>“ClientDetailScreen”打开。但是,您也可以从完全不同的选项卡(例如仪表板)到达那里,您可以在其中收到来自客户的消息,当您单击他们的名字时,您也可以进入 ClientDetailScreen。这样做的意义在于,可以打开 N 个 ClientDetailScreen。
从 ClientDetailScreen,您可以访问与您进入屏幕的特定客户端相关的各种子屏幕。现在问题出现了。
好吧,为了使用 Provider 包在所有可能的子屏幕上访问有关此客户端的一些信息,您在 ClientDetailScreen 的顶层创建了一个 ChangeNotifier,这意味着每个屏幕都有自己的可访问提供程序。这意味着在所有子屏幕和相关小部件中您可以执行以下操作:
context.read<ClientProvider>();
,您每次都会访问正确的数据。
有了Riverpod,这个问题似乎就没那么容易解决了。 Riverpod 对于创建提供程序更加严格。基本上,它们是在全球范围内使用后立即创建的。我知道家庭构造函数可以区分正确的实例,但是我对选择该路径犹豫不决,尤其是当这意味着我必须以某种方式将 clientId 分布在所有子小部件上时,这似乎并不正确。我更倾向于这样一个事实:应用程序的编写方式存在根本性错误。我试图通过执行本地 ProviderScope 来解决这个问题,该 ProviderScope 将封装整个 ClientDetailScreen,希望所有子小部件都能访问正确的提供程序。然而,由于某种原因,所有子屏幕都被推到与 ClientDetailScreen 相同的级别,这意味着它们无法访问正确的范围,并且由于某些依赖性,我无法将 ProviderScope 置于更高的位置。
您解决过类似的问题吗?感谢您的任何回复。
两种解决方案。 最简单的一种:使用家庭提供者。 我确信每个 ClientDetailScreen 都可以产生一个唯一的标识符,它可以是家庭密钥。 每个提供者都有自己的生命周期和状态。
稍微困难一点,但更像“Provider-package”:使用子 ProviderScope,位于 ClientDetailScreen 上方并覆盖提供者,就像您可能已经使用 Provider-package 一样。
后者仍然受到支持,但不鼓励,因为家庭更加灵活,特别是在代码生成方面。