Flutter:调整Widget大小后出现LateInitializationError问题求助
LateInitializationError错误 调整Widget大小后,出现针对items_head的LateInitializationError错误,相关代码如下:
class Head_View extends StatefulWidget { Head_View({Key? key}) : super(key: key); late List<AppointmentItemWrapper> items_head; //late MultiChildRenderObjectWidget DTIT_head; --> **EDIT ON 20230605** @override State<Head_View> createState() => _Head_ViewState(); } class _Head_ViewState extends State<Head_View> { @override void initState() { widget.items_head = [ AppointmentItemWrapper( ID: 111, key: UniqueKey(), startDateTime: DateTime(2022, 1, 1, 8, 00, 0), endDateTime: DateTime(2022, 1, 1, 9, 30,0), position: 0, text: "Event N1", positiondragging: (double valxx) { print("HAHAH"); }, ), ]; super.initState(); } @override Widget build(BuildContext context) { return DynamicTimeline( key: _myWidgetKey_DTIT_head, firstDateTime: DateTime(2022, 1, 1,7,0,0), lastDateTime: DateTime(2022, 1, 1,18,0,0), labelBuilder: DateFormat('hh:mm').format, items: widget.items_head, ); } }
原本认为initState()仅在首次构建前调用,调整Widget大小时只会重新调用build()方法,此时items_head应该已处于可用状态,这个理解有问题吗?
问题分析
你的理解存在偏差:initState()确实只在State对象首次创建时执行一次,但问题出在items_head的存储位置——它被定义在Head_View这个StatefulWidget类中。
当Widget大小调整时,父Widget可能触发重建,重新创建Head_View的新实例(如果父Widget的build方法里直接生成Head_View()且未指定稳定的key)。此时若Flutter复用了原有的_Head_ViewState对象(未指定key或key相同时,Flutter会尝试复用State),新的Head_View实例的items_head是late修饰但未初始化的状态,而initState()不会再次执行,导致build()中访问widget.items_head时触发LateInitializationError。
另外,StatefulWidget本身是不可变设计,不应该在State中修改它的字段,这违反了Flutter的Widget设计原则。
解决方案
把items_head移到_Head_ViewState类内部,作为State的成员变量:
class Head_View extends StatefulWidget { Head_View({Key? key}) : super(key: key); @override State<Head_View> createState() => _Head_ViewState(); } class _Head_ViewState extends State<Head_View> { late List<AppointmentItemWrapper> items_head; @override void initState() { super.initState(); items_head = [ AppointmentItemWrapper( ID: 111, key: UniqueKey(), startDateTime: DateTime(2022, 1, 1, 8, 00, 0), endDateTime: DateTime(2022, 1, 1, 9, 30,0), position: 0, text: "Event N1", positiondragging: (double valxx) { print("HAHAH"); }, ), ]; } @override Widget build(BuildContext context) { return DynamicTimeline( key: _myWidgetKey_DTIT_head, firstDateTime: DateTime(2022, 1, 1,7,0,0), lastDateTime: DateTime(2022, 1, 1,18,0,0), labelBuilder: DateFormat('hh:mm').format, items: items_head, ); } }
调整后:
items_head属于State对象,只要State不被销毁,就会保持初始化后的状态,即使Widget重建,只要State被复用,items_head依然可用。- 符合Flutter设计规范:State负责管理可变状态,Widget仅作为配置信息传递。
如果需要从父Widget传递初始数据,可通过Head_View构造函数传入,在initState或didUpdateWidget中处理,但核心原则是把可变状态放在State中。
内容的提问来源于stack exchange,提问作者Lukas Fürst

