乐趣区

flutter的key在widget list的作用以及必要性

在做一个 flutter 的项目过程中,体会到了 key 在 widget 渲染中发挥的作用以及开发者需要避免的坑,在次提出共勉
与 react 的 diff 算法类似(vue 的也是),flutter 在渲染同级类似的 item 的时候也是采用 key 值判断来重新渲染的。因此如果你的业务中如果包含了一个同类型的 widget list,记得要为每个 widget 加上一个 key,否则 flutter 也是默认使用 item 在 list 的 index 作为 key,这样就会遇到下面这个常见的坑了:
假设原本有一个 list,
list = [widget0: {key: 0, …}, widget1: {key: 1, …}, widget2: {key: 2, …}]
对应的视图为:

现在我们删除中间的 widget1,list 更新成:
list = [widget0: {key: 0, …}, widget2: {key: 1, …}]
对应的视图为:
可以看到,widget1 没有被删除,而是 widget2 被删除了,这显示是错误的。原因便在于:虽然 widget1 在 list 中确实删除了,但现在 widget2 的 key 变成了 1 当 fultter 执行 diff 算法的时候,由于它是根据前后 widget 的 key 是否变化来判断的而 widget2 的 key 是 1,fultter 会认为原来 key 为 1 的那个 widget(就是 widget1) 没有变化,所以不更新,而删除掉原来 key 为 2 的 widget(就是 widget2)。
知道了原因后,为每个 widget 加上一个 uuid,问题就解决了:

注:如果 widget 是 stateless 的,不加 key 也能够正确删除。可能的原因大概是 stageless 的 widget 每次都需要重新绘制,因此不管 key 变不变化都是重绘的,而 stateful 则是根据 state 有没有变化来重绘,这样由于 key 没有变所以 state 也没有改变。但是作为开发者的我们,都应该养成添加 key 的习惯。
如有错误,还望指出!

退出移动版