Flutter构造函数跨页传值 pop返回上一页时值为null
问题核心原因
传值失效是几个逻辑错误直接导致的:
- 传值方向完全写反:在AddUser页面手动实例化
Register(names: saaaaa.text)创建的是一个全新的Register组件对象,和路由栈里已经存在的Register页面没有任何关联,根本不会修改原有页面的状态 - 错误手动传递StatefulWidget参数:Register里重复定义了和Widget同名的
names字段,还手动把参数传给State,破坏了Flutter State默认访问Widget属性的机制 - 路由返回逻辑缺失:push到AddUser时没有设置await接收返回值,pop时也没有携带输入的参数,甚至AddUser的组件树里根本没加入保存按钮,逻辑根本触发不了
- 列表生成逻辑错误:每次build都重新调用
getUserModel()生成只有单个元素的新列表,根本没法累加保存多个用户的输入
修复方案
按照Flutter路由传值的标准逻辑实现即可:push跳转下一页时通过构造函数给下一页传参;下一页返回时通过Navigator.pop的第二个参数把数据带回上一页,上一页用await接收返回值后更新状态。
修正后代码
Register页面
// 补全你用到的UserModel定义 class UserModel { final String name; UserModel({required this.name}); } class Register extends StatefulWidget { const Register({super.key, this.names}); final String? names; @override State<Register> createState() => _RegisterState(); } class _RegisterState extends State<Register> { // 用固定列表存储所有添加的用户,不要每次build重新生成 List<UserModel> userList = []; @override void initState() { super.initState(); // 初始如果有传入默认name,先加入列表 if (widget.names != null && widget.names!.trim().isNotEmpty) { userList.add(UserModel(name: widget.names!.trim())); } } @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Padding( padding: EdgeInsets.only(top: 10, bottom: 10), child: Text( 'Seleccione una categoría:', textAlign: TextAlign.center, style: TextStyle(color: Colors.black), ), ), Expanded( child: ListView.builder( itemCount: userList.length, itemBuilder: (BuildContext ctx, int index) { return Container( margin: const EdgeInsets.all(20), height: 150, child: Stack( children: [Text(userList[index].name)], ), ); }, ), ), FloatingActionButton( backgroundColor: Colors.indigo[900], onPressed: () async { // 等待AddUser页面返回结果 final result = await Navigator.push( context, MaterialPageRoute(builder: (_) { return const AddUser(idUser: ''); }), ); // 收到有效输入后更新列表刷新UI if (result != null && result is String && result.trim().isNotEmpty) { setState(() { userList.add(UserModel(name: result.trim())); }); } }, child: const Icon(Icons.add, color: Colors.white), ), ], ); } }
AddUser页面
class AddUser extends StatefulWidget { final String? idUser; const AddUser({super.key, required this.idUser}); @override State<AddUser> createState() => _AddUserState(); } class _AddUserState extends State<AddUser> { final formKey = GlobalKey<FormState>(); // 把无意义的控制器名改成可读的名称 final nameController = TextEditingController(); @override void dispose() { // 页面销毁时释放控制器,避免内存泄漏 nameController.dispose(); super.dispose(); } @override Widget build(BuildContext context) => Scaffold( appBar: AppBar( automaticallyImplyLeading: false, title: const Text( 'Please Enter Your Details', textAlign: TextAlign.center, )), body: SafeArea( child: ListView( padding: const EdgeInsets.all(16), children: [ buildName(), const SizedBox(height: 12), // 原来的代码漏加保存按钮,这里补上;如果要保留自定义ButtonWidget直接替换即可 buildButton(), ], ), ), ); Widget buildName() => buildTitle( title: 'Name', child: TextFormField( controller: nameController, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: 'Your Name', ), // 删除无效的onChanged逻辑,控制器会自动持有输入内容 ), ); Widget buildButton() => ElevatedButton( onPressed: () { final inputName = nameController.text.trim(); if (inputName.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('姓名不能为空'))); return; } // 把输入内容作为pop的第二个参数传回上一页,不要手动new Register Navigator.pop(context, inputName); }, child: const Text('Save'), ); Widget buildTitle({ required String title, required Widget child, }) => Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( title, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18), ), const SizedBox(height: 8), child, ], ); }
额外提示:不要在State里手动定义和Widget同名的参数接收构造函数值,State可以直接通过
widget.xxx访问对应StatefulWidget的公开属性,手动传参很容易出现状态不同步的问题。
内容的提问来源于stack exchange,提问作者ashish rana
相关产品推荐
相关产品推荐

