我正在key
通过这篇文章学习小部件的颤动概念。我很困惑,即使两个无状态子小部件中没有键,它们仍然可以正确交换位置。为什么?这不是key
父母跟踪哪个孩子是哪个孩子的唯一方法吗?(以便它可以交换他们的位置)。请检查dartpad中的代码
1 回答
在等待更好的答案时,我有点弄清楚那里发生了什么(作为一个新手,我可能是错的):
在无状态情况下,当您交换小部件时,会发生三个事实:(1)两个小部件实例确实改变了小部件树中的位置,但是(2)对应的元素树保持不动(这是因为每个对应的小部件类型都有没变)。(3) 元素树中唯一改变的是元素对小部件的引用(以反映小部件树中的顺序变化)。由于无状态小部件完全通过自身的信息更新屏幕(没有外部状态),这使得交换正确地显示在屏幕上。
在 statefull without key 的情况下,当您交换小部件时,事情的发生与上述无状态情况相同,即所有三个事实都再次发生。但是为什么屏幕上没有显示交换?这是因为对于有状态的小部件,屏幕更新依赖于与元素树中相应元素关联的外部对象(即状态)。因此,即使小部件实例确实交换了位置(蓝色,红色 --> 红色,蓝色),颤动仍然将它们绘制为(蓝色,红色),因为这是元素树中的顺序(永远不会改变)。
在 stateful with key 的情况下,只发生三者中的第一个事实。其他两个不再是真的了。这里发生的事情是元素树确实根据小部件树的变化而变化。它通过匹配两侧的键和类型来实现这一点。在此之后,交换正确显示在屏幕上,因为元素确实从 (blue,red) 变为 (red,blue)。请记住,元素树,而不是小部件树,是这里的老板。小部件树只是一组配置,元素树是负责在屏幕上绘画的人。
还有一个谜题留给我。在没有键的有状态情况下,每次交换发生时,Flutter 都会调用build
状态对象的方法。但是有了一个键,build
就从来没有调用过。为什么?我猜那是因为元素树的引用发生了变化。即,每次引用更改时,颤振调用build
以重建相应小部件的状态。另一方面,如果有密钥,则引用永远不会改变。所以不需要flutter来重建状态。
期待有人可以证实我的理解。