Flutter报错:不可空局部变量title使用前必须赋值问题解决
报错原因
- Dart空安全机制要求非空类型变量必须在使用前完成赋值,你声明的
String title是非空类型,仅在TextField的onChanged回调里赋值,编译期无法保证用户点击添加按钮前onChanged一定被触发(比如用户直接点击按钮不输入任何内容),因此编译不通过。 - 你当前用
StatelessWidget的局部变量存储输入内容的方式也不规范,若后续组件触发重build,局部变量title会被重置,存在输入内容丢失的风险。 - 额外问题:你在
TasksScreen的底部弹窗逻辑里手动调用了AddTaskScreen(...).build(context),属于错误用法,会引发未知的渲染异常。
解决方案
方案1:快速适配空安全(简单场景可用)
直接调整变量类型适配空安全规则,同时增加非空校验:
- 将
AddTaskScreen里的String title;修改为可空类型String? title; - 给回调指定明确的参数类型,把
final Function callBack;改为final Function(String) callBack; - 修改添加按钮的点击逻辑,增加非空判断:
onPressed: () { // 仅在输入内容不为空时触发回调 if (title != null && title!.trim().isNotEmpty) { callBack(title!.trim()); } },
方案2:标准规范写法(推荐)
改用StatefulWidget + TextEditingController获取输入内容,这是Flutter官方推荐的TextField输入获取方案,稳定性更高:
第一步:修改AddTaskScreen代码
import 'package:flutter/material.dart'; class AddTaskScreen extends StatefulWidget { // 明确指定回调的参数类型 final Function(String) callBack; const AddTaskScreen({required this.callBack, super.key}); @override State<AddTaskScreen> createState() => _AddTaskScreenState(); } class _AddTaskScreenState extends State<AddTaskScreen> { // 创建输入控制器 final TextEditingController _taskInputController = TextEditingController(); @override void dispose() { // 销毁控制器,避免内存泄漏 _taskInputController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( height: 350, color: const Color(0xff757575), child: Container( padding: const EdgeInsets.all(20), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topRight: Radius.circular(20), topLeft: Radius.circular(20), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Add Task', textAlign: TextAlign.center, style: TextStyle( color: Colors.lightBlueAccent, fontSize: 24, ), ), const SizedBox(height: 20,), TextField( // 绑定输入控制器 controller: _taskInputController, textAlign: TextAlign.center, autofocus: false, style: const TextStyle( color: Colors.black, fontSize: 15, ), decoration: const InputDecoration( focusColor: Colors.lightBlueAccent, hintText: 'Type a Task', hintStyle: TextStyle( color: Colors.grey, fontSize: 12, ), ), ), const SizedBox(height: 20,), TextButton( onPressed: () { String inputContent = _taskInputController.text.trim(); if (inputContent.isNotEmpty) { widget.callBack(inputContent); } }, style: TextButton.styleFrom( backgroundColor: Colors.lightBlueAccent, ), child: const Text( 'Add', style: TextStyle( color: Colors.white, fontSize: 18, ), ), ), ], ), ), ); } }
第二步:修复TasksScreen里的底部弹窗逻辑
去掉手动调用build(context)的错误代码:
showModalBottomSheet( context: context, builder: (context) => SingleChildScrollView( child: Container( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom), // 直接传AddTaskScreen实例,不要手动调用build方法 child: AddTaskScreen( callBack: (String taskTitle) { setState(() { print(taskTitle); tasks.add(Task(name: taskTitle)); }); Navigator.pop(context); }, ), ), ), );
内容的提问来源于stack exchange,提问作者user16307243
相关产品推荐
相关产品推荐

