Flutter中如何用async/await实现用户输入后再创建ListView元素
解决Flutter ListView元素提前生成的问题
你的核心问题有两个:
- 点击按钮时先创建了ListView元素,再弹出输入框,顺序搞反了
- 错误地直接实例化
_MyDialogState来获取输入值,这不符合Flutter的状态管理逻辑
正确的做法是先等待用户输入完成,再创建对应的ListView元素,用async/await来控制流程,同时用列表存储每个元素的内容,而不是单纯计数。
修正后的完整代码
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( home: MyHome(), ); } } class MyHome extends StatelessWidget { const MyHome({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: const Text('My App'), ), body: const MyTile(), ); } } // 直接写一个返回输入内容的对话框函数,无需单独的StatefulWidget Future<String?> showInputDialog(BuildContext context) { final TextEditingController controller = TextEditingController(); return showDialog<String>( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('输入名称'), content: TextField( controller: controller, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: '请输入名称', ), ), actions: <Widget>[ TextButton( child: const Text('取消'), onPressed: () { Navigator.pop(context); }, ), TextButton( child: const Text('添加'), onPressed: () { // 点击添加时,把输入内容返回给调用方 Navigator.pop(context, controller.text); }, ) ], ); }, ); } class MyTile extends StatefulWidget { const MyTile({super.key}); @override State<MyTile> createState() => _MyTileState(); } class _MyTileState extends State<MyTile> { // 用列表存储每个tile的内容,替代单纯的计数 final List<String> _tileContents = []; @override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: _tileContents.length, itemBuilder: (BuildContext context, index) { return ListTile( leading: const Icon(Icons.list), trailing: Text(_tileContents[index]), ); }, ), floatingActionButton: FloatingActionButton( onPressed: () async { // 先等待用户完成输入并确认 final String? input = await showInputDialog(context); // 如果输入不为空,再添加元素 if (input != null && input.isNotEmpty) { setState(() { _tileContents.add(input); }); } }, child: const Icon(Icons.add), ), ); } }
关键修改点
- 调整流程顺序:把FAB的点击事件改成
async函数,用await等待对话框返回结果,确认用户输入后再添加ListView元素,避免提前生成空元素。 - 状态管理优化:用
List<String>存储每个tile的内容,替代原来的计数变量,直接对应每个元素的显示文本。 - 重构对话框:去掉多余的
MyDialogStatefulWidget,改成直接返回输入内容的函数,通过Navigator.pop把输入值传递回调用方,避免错误的状态实例化操作。
内容的提问来源于stack exchange,提问作者MantiS
相关产品推荐
相关产品推荐

