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

Flutter中FutureBuilder的ListView.builder删除条目后如何更新UI?

功能实现方案

问题根因

你遇到的现象由以下几个错误写法共同导致:

  1. 直接修改AsyncSnapshot的data属性:该数据是Future执行完成后的只读快照,且你每次触发setState页面重绘时,FutureBuilder都会重新执行_myFutureBuilder()从数据库拉取旧数据,覆盖你对快照的修改
  2. 给ListView.builder加了UniqueKey:每次setState都会强制整个列表全量重建,无法实现增量条目更新
  3. 数据库返回的QueryResultSet属于不可变集合,直接调用removeAt方法不会实际修改集合内容

修复步骤

  1. 在State类中新增本地可变列表缓存数据源,同时新增变量存储Future实例,避免每次重绘重复执行异步请求
  2. 拿到异步返回的查询结果后,先转换为可变List再赋值给本地缓存
  3. 列表数据源完全使用本地缓存,删除操作先执行数据库删除逻辑,成功后再修改本地缓存触发UI更新
  4. 移除不必要的UniqueKey,可根据条目唯一标识设置ValueKey优化列表渲染性能

完整修改示例

首先是State类的变量与初始化部分:

class _YourPageState extends State<YourPage> {
  // 存储异步请求实例,避免重复执行
  late Future _dataFuture;
  // 本地可变数据源,所有UI渲染、列表操作都基于该变量
  List _installedMuseums = [];

  @override
  void initState() {
    super.initState();
    // 页面初始化时仅执行一次异步请求
    _dataFuture = _myFutureBuilder();
  }

然后是FutureBuilder部分的修改:

FutureBuilder(
  future: _dataFuture,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    } else if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        return const Text('Error');
      } else if (snapshot.hasData) {
        // 将不可变的查询结果转为可变List赋值给本地缓存
        _installedMuseums = List.from(snapshot.data);
        return Padding(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            children: [
              Flexible(
                child: ListView.builder(
                  // 移除UniqueKey,避免全量重建
                  itemCount: _installedMuseums.length,
                  itemBuilder: (context, index) {
                    final currentItem = _installedMuseums[index];
                    return Card(
                      elevation: 4,
                      // 用条目唯一标识做key,优化渲染性能
                      key: ValueKey(currentItem['name']),
                      child: ListTile(
                        trailing: const Icon(Icons.delete),
                        title: Text(currentItem["name"]),
                        onTap: () async {
                          // 先执行数据库删除操作
                          await _deleteOps(currentItem["name"]);
                          // 删除成功后修改本地缓存触发UI更新
                          setState(() {
                            _installedMuseums.removeAt(index);
                          });
                        },
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
        );
      } else {
        return const Text('Empty data');
      }
    } else {
      return Padding(
        padding: const EdgeInsets.all(20.0),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: const [
              CircularProgressIndicator(),
              SizedBox(height: 20),
              Text(
                "loading...",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ],
          ),
        ),
      );
    }
  }
)

可选优化方案

如果你的数据量不大,不想维护本地缓存,可以删除成功后直接重新触发一次数据库查询:

onTap: () async {
  await _deleteOps(currentItem["name"]);
  setState(() {
    // 重新执行异步请求拉取最新数据
    _dataFuture = _myFutureBuilder();
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 09:48:00