我有一个实体对象,为简单起见,我们现在称其为 Todo
。我想要一个小部件,我可以在其中同时编辑多个这些待办事项,例如 EditableTodoList
(这将显示 EditableTodo
的列表)。
这个小部件会收到一个 List<Todo>
以及类似 Function onTodoEdited(Todo)
的东西。
我正在尝试使用不可变数据,因此当正在编辑 EditableTodo
时(并且事件被传播到包含 EditableTodoList
的小部件),我会创建一个新的 List<Todo>
包含更新后的 Todo
,但随后 EditableTodoList
将重建其所有 EditableTodo
。
我该如何优化,只重建相关的 EditableTodo
?我不想修改道具原始 List<Todo>
,因为这隐藏了一个重要的细节。
背景:当前状态在一肘内,我对每个 context.select
列表项都 EditableTodo
-ing 状态中相应的 Todo
,这样只有编辑过的项目会重建。我想将这个 EditableTodoList
与肘分开。
理论上我认为这是不可能的,因为 EditableTodoList
被赋予了新的属性,所以它必须重建,这意味着所有的子树都会被重建。 EditableTodo
不能是 const
,因为它的 prop 不是常量。
但是,将 EditableTodoList
与肘分开的最优雅的方法是什么?由于它只需要一个 List<Todo>
来显示,因此应该可以以某种方式优化未更改的 Todo
s
答案 0 :(得分:1)
您应该考虑小部件、元素和渲染树的工作方式,以便关注。关于 Flutter 的渲染机制有一个很棒的 video。重建树时,仅使用 compares 和运行时类型值构建 key 两个小部件。这意味着如果您更改 Text
小部件的字符串值,将再次使用具有变异数据的相同渲染对象。不会创建新的渲染对象,这意味着渲染树上不会发生不必要的重建。与渲染树相比,重建小部件树并不昂贵。
如果两个小部件的 runtimeType
和 key
属性是
operator==
,则新小部件替换旧小部件
通过更新底层元素(即,通过调用 Element.update
使用新的小部件)。否则,旧元素将从
树,新的小部件被膨胀成一个元素,新的元素
被插入到树中。
最小化 ListView
中的构建范围是有限制的。 ListView
本身应该重建以更改元素。所以你不能在重建时定位列表中的特定元素。因此,不可变集合在此上下文中无关紧要,因为框架不关心值,而关心键和运行时类型。您可以传递一个完全修改过的列表,也可以只更改一个元素,这将具有相同的效果。
如果您担心每次修改单个 Todo
时都会创建新的渲染对象,请不要担心,根本没有。框架通过“回收”渲染对象来帮助您。