为什么StatefulWidget传入新构造数据时不会重新构建对应的State对象?
问题核心原因
Flutter框架对StatefulWidget的State实例复用规则是:当新构建的Widget和之前同位置的Widget的runtimeType、key两个属性完全相同时,会复用已有的State实例,不会重新执行createState()方法,initState()生命周期自然也只会在State第一次创建时触发一次。
你两次构建TrainsPage时没有指定自定义key,所以框架复用了第一次创建的_TrainsPageState实例,只更新了State实例持有的widget属性,但是你把routes存在了State的本地变量_routes里,又没有监听widget.routes的变化,所以数据一直停留在第一次传入的空列表状态。
解决方法(三选一即可)
方案1:给TrainsPage指定唯一标识的Key
当Key发生变化时,框架会直接销毁旧的State实例,创建新的State实例,initState()会正常触发读取新的routes:
Widget pageSelector() { if (_selectedIndex == 2) { // 用能标识routes变化的属性作为ValueKey,比如routes的hashCode return TrainsPage(key: ValueKey(_routes.hashCode), routes: _routes); } else return const Text(""); }
方案2:在State中重写didUpdateWidget生命周期监听属性变化
该生命周期会在State持有的widget属性更新时触发,在此处同步本地的_routes即可:
class _TrainsPageState extends State<TrainsPage> { List<RSRoute> _routes = List.empty(); @override void initState() { super.initState(); _routes = List<RSRoute>.from(widget.routes); } // 新增这段代码 @override void didUpdateWidget(covariant TrainsPage oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.routes != widget.routes) { setState(() { _routes = List<RSRoute>.from(widget.routes); }); } } }
方案3:直接使用widget.routes,无需本地存副本
如果TrainsPage内部不需要修改routes列表,完全可以直接使用widget.routes做展示,不需要在State里单独存一份_routes,也就不会有数据同步的问题。
内容的提问来源于stack exchange,提问作者Alexander Roehnisch
相关产品推荐
相关产品推荐

