为什么将StatefulWidget添加到TabItem列表末尾会触发initState和dispose
问题根本原因
这一现象是DefaultTabController配套的TabBarView懒加载逻辑、Flutter的Element树Diff规则共同作用的结果:
TabBarView默认采用懒加载策略,只有子页面进入视口时才会初始化对应StatefulWidget,子页面移出视口且未配置保活逻辑时会触发dispose- 列表操作的位置差异会触发完全不同的Diff逻辑,最终表现出生命周期回调的差异
widgetList.add()触发双回调的原因
add()操作是在列表末尾插入新Tab,原有所有Tab的索引不会发生变化:
当你调用add()后通常会主动跳转至新增的末尾Tab,跳转过程中新增Tab进入视口触发initState;如果你的TabBarView未配置页面保活,跳转后新增Tab因布局计算、缓存范围限制等原因临时移出可视范围,就会立刻触发dispose,最终表现为两个生命周期方法连续触发。
widgetList.insert()无回调的原因
insert()操作是在列表非末尾位置插入新Tab,插入位置之后的所有原有Tab索引都会+1:
如果你没有给每个Tab对应的Widget指定唯一Key,Flutter的Diff逻辑会直接复用对应索引位置的已有Element,不会为新插入的Widget创建新Element,自然不会触发生命周期回调;同时插入非末尾位置后如果没有主动切换到新增Tab的索引,新增Tab不会进入视口触发懒加载,也不会产生生命周期回调。
补充:如果给每个TabWidget都指定全局唯一的
Key,Diff逻辑可以正确识别新插入的Widget,此时调用insert()方法后只要新增Tab进入视口,也会正常触发initState。
规避方案
- 给所有Tab页的State混入
AutomaticKeepAliveClientMixin,重写wantKeepAlive返回true,已经加载过的Tab不会被意外销毁,避免反复触发生命周期回调 - 操作Tab列表后,等待布局更新完成再执行页面跳转操作,避免页面临时加载又立刻销毁的异常情况
内容的提问来源于stack exchange,提问作者mlopez99
相关产品推荐
相关产品推荐

