生成器与 GlobalKey

Builder versus GlobalKey

许多与构建 Flutter UI 相关的问题归结为错误 BuildContext(例如显示 SnackBar)。答案通常是使用 BuilderGlobalKey。两者都有效,但我注意到 GlobalKey 的文档指出:

Global keys are relatively expensive. If you don't need any of the features listed above, consider using a Key, ValueKey, ObjectKey, or UniqueKey instead.

所指的特征是唯一标识和子树重育。在这些情况下使用 GlobalKey 的 "relative expense" 是否足以使用 Builder 代替?

GlobalKey 很昂贵很可能与您可能需要大量密钥的情况有关,例如 ListView.

的 children

我怀疑 GlobalKeySnackBar 的成本是否重要。您不太可能创建很多。

我们倾向于避免 GlobalKey 的真正原因与性能无关。这与它在 flutter 中打破了一些模式有关。

根据定义,小部件不应该能够访问其他小部件的具体信息(例如它们的大小或位置)。并且 GlobalKey 授予访问此类信息的能力;允许人们做反模式的事情。

GlobalKey 视为 弹出 Flutter 反应层的手段。

人们试图使用 GlobalKey 做什么的几个例子:

  • 有一个 public 单身人士 GlobalKey。用作不提升状态的手段。使小部件之间的交互难以预测,因为这种关系不再是单向的(父 -> 子级变成双向关系)
  • 使用 GlobalKey 计算布局的大小。然后使用此信息触发重新渲染。相反,这是 RenderObject 的作用,不应在小部件中完成。它使布局更难维护

Builder 和类似的另一方面不要打破这些模式。因为,根据定义 Builder 什么都不做 。这只是使用不同 BuildContext 的一种巧妙方式。

这通常意味着,如果您可以使用 Builder 而不是 GlobalKey 来解决您的布局问题,那么您就走在了可维护布局的正确轨道上。


那什么时候使用GlobalKey

好吧,如果可以的话,永远不要。尝试改用 context.ancestorStateOfTypecontext.inheritWidgetOfExtactType 之类的东西。您可能还想考虑为特定布局创建自定义 RenderObject。如果您需要 parent/children

之间的关系,RenderObject 结合 parentData 也可能是您想要的

虽然这可能更复杂。它可以消耗比你想要的更多的时间。或者您可能会陷入使用当前 API 难以实现的边缘情况。

在这种情况下,只要您知道潜在的后果,就可以使用 GlobalKey