BloC状态更新后自定义TextField未更新的问题及解决方法
问题解答
initState不调用是正常情况吗?
是正常的。initState是Flutter StatefulWidget的生命周期方法,仅在Widget第一次被插入到Widget树时执行一次。当父组件(此处为ProductScreen中的BlocBuilder)因状态更新触发重建时,只要AppMoneyField未被移除后重新插入、也未更换唯一Key,State对象就会被复用,不会再次调用initState,仅执行build方法——这是Flutter的常规优化行为。
解决方法
方法1:重写didUpdateWidget更新控制器(推荐)
在AppMoneyField的State类中添加didUpdateWidget方法,对比新旧initialValue,当值发生变化时更新TextEditingController的文本:
@override void didUpdateWidget(covariant AppMoneyField oldWidget) { super.didUpdateWidget(oldWidget); // 检查initialValue是否发生变化 if (oldWidget.initialValue != widget.initialValue) { final newText = widget.initialValue != null ? NumberFormat(".##").format(widget.initialValue) : ""; // 保持光标位置合理,避免打断用户操作 controller.value = controller.value.copyWith( text: newText, selection: TextSelection.collapsed(offset: newText.length), ); } }
如果需要避免干扰用户正在输入的操作,可以增加焦点判断:
@override void didUpdateWidget(covariant AppMoneyField oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.initialValue != widget.initialValue && !controller.hasFocus) { final newText = widget.initialValue != null ? NumberFormat(".##").format(widget.initialValue) : ""; controller.text = newText; } }
方法2:强制重建Widget(不推荐,仅作补充)
若不想处理生命周期方法,可以给AppMoneyField设置ValueKey,当initialValue变化时,Key同步变化,强制Flutter销毁旧State并创建新实例,让initState再次执行:
AppMoneyField( key: ValueKey(state.cost), // 用initialValue作为Key title: "Value", initialValue: state.cost, isMandatory: true, onTextChange: (value) { context.read<AddPositionBloc>().add(ChangeCostEvent(double.tryParse(value))); }, )
此方法虽简单,但会导致Widget完全重建,性能不如直接更新控制器高效,仅适合简单场景。
内容的提问来源于stack exchange,提问作者giordy16
相关产品推荐
相关产品推荐

