You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),
      ),
    );
  }
}

关键修改点

  1. 调整流程顺序:把FAB的点击事件改成async函数,用await等待对话框返回结果,确认用户输入后再添加ListView元素,避免提前生成空元素。
  2. 状态管理优化:用List<String>存储每个tile的内容,替代原来的计数变量,直接对应每个元素的显示文本。
  3. 重构对话框:去掉多余的MyDialog StatefulWidget,改成直接返回输入内容的函数,通过Navigator.pop把输入值传递回调用方,避免错误的状态实例化操作。

内容的提问来源于stack exchange,提问作者MantiS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:43:17