Flutter在initState()中使用Provider触发空检查运算符异常求解决方案
解决Provider数据作为TextField初始值时的空指针异常
问题原因
你代码里的WidgetsBinding.instance.addPostFrameCallback会在第一次build方法执行完成后才触发,而第一次build时_lastNameController和_firstNameController还未被赋值(仍是null),此时用!强制解包就会抛出Null check operator used on a null value异常。
解决方案
方案1:提前初始化控制器,后续修改文本
直接创建非空的控制器实例,在回调中修改文本内容,避免build时控制器为null:
TextEditingController _lastNameController = TextEditingController(); TextEditingController _firstNameController = TextEditingController(); @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final myProvider = Provider.of<MyProvider>(context, listen: false); _lastNameController.text = myProvider.lastName; _firstNameController.text = myProvider.firstName; }); } @override Widget build(BuildContext context) { return Row( children: [ MyTextField(controller: _lastNameController, hintText: 'Last Name'), const Spacer(), MyTextField(controller: _firstNameController, hintText: 'First Name'), ], ); }
方案2:在didChangeDependencies中初始化控制器
didChangeDependencies会在initState之后、第一次build之前执行,且可以安全获取Provider数据,同时加判断避免重复初始化:
TextEditingController? _lastNameController; TextEditingController? _firstNameController; @override void didChangeDependencies() { super.didChangeDependencies(); // 仅在控制器未初始化时赋值 if (_lastNameController == null) { final myProvider = Provider.of<MyProvider>(context, listen: false); _lastNameController = TextEditingController(text: myProvider.lastName); _firstNameController = TextEditingController(text: myProvider.firstName); } } @override Widget build(BuildContext context) { return Row( children: [ MyTextField(controller: _lastNameController!, hintText: 'Last Name'), const Spacer(), MyTextField(controller: _firstNameController!, hintText: 'First Name'), ], ); }
方案3:在build中懒加载控制器
使用??=运算符,仅当控制器为null时才初始化,确保build时控制器已存在:
TextEditingController? _lastNameController; TextEditingController? _firstNameController; @override Widget build(BuildContext context) { final myProvider = Provider.of<MyProvider>(context, listen: false); // 懒加载初始化控制器 _lastNameController ??= TextEditingController(text: myProvider.lastName); _firstNameController ??= TextEditingController(text: myProvider.firstName); return Row( children: [ MyTextField(controller: _lastNameController!, hintText: 'Last Name'), const Spacer(), MyTextField(controller: _firstNameController!, hintText: 'First Name'), ], ); }
内容的提问来源于stack exchange,提问作者Nao COMATSU
相关产品推荐
相关产品推荐

