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

FutureBuilder无法实时展示新增列表元素,StreamBuilder适配报错求助

Flutter中FutureBuilder不更新、StreamBuilder类型不兼容的解决方法

问题原因

  1. FutureBuilder无法实时更新:FutureBuilder的future参数只会在组件初始化时执行一次,新增数据后不会自动重新调用数据获取方法,所以列表不会刷新,必须手动触发重新执行future。
  2. StreamBuilder报错:StreamBuilder要求传入Stream类型的数据源,但你传入的是Future,类型不匹配,所以抛出future is not a subtype of stream错误。

解决方案一:用StatefulWidget + setState刷新FutureBuilder

通过将数据获取的Future存在State中,新增数据后调用setState重新赋值Future,让FutureBuilder重新执行并刷新列表。

完整示例代码:

class NotePage extends StatefulWidget {
  const NotePage({super.key});

  @override
  State<NotePage> createState() => _NotePageState();
}

class _NotePageState extends State<NotePage> {
  late Future<List<Map>> _noteListFuture;

  @override
  void initState() {
    super.initState();
    // 初始化加载数据
    _noteListFuture = _getNoteList();
  }

  // 获取笔记列表的方法
  Future<List<Map>> _getNoteList() async {
    return await sq.ReadData('SELECT * FROM notes');
  }

  // 刷新列表的方法,新增数据后调用
  void _refreshNoteList() {
    setState(() {
      // 重新赋值Future,触发FutureBuilder刷新
      _noteListFuture = _getNoteList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 新增按钮示例,点击后执行新增逻辑并刷新
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // 这里执行新增笔记的数据库操作
          // await sq.InsertData(...);
          // 新增完成后刷新列表
          _refreshNoteList();
        },
        child: const Icon(Icons.add),
      ),
      body: FutureBuilder(
        future: _noteListFuture,
        builder: (context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data.length,
              itemBuilder: (context, index) {
                return Container(
                  height: 50,
                  child: Card(
                    child: Text('${snapshot.data[index]['note']}'),
                  ),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Text('加载失败:${snapshot.error}');
          } else {
            // 加载中状态
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

解决方案二:将Future转为Stream,用StreamBuilder实现自动更新

通过StreamController手动管理数据流,每次数据变更时重新获取数据并发送到流中,StreamBuilder会自动监听流的变化刷新列表。

完整示例代码:

class NotePage extends StatefulWidget {
  const NotePage({super.key});

  @override
  State<NotePage> createState() => _NotePageState();
}

class _NotePageState extends State<NotePage> {
  late StreamController<List<Map>> _noteStreamController;

  @override
  void initState() {
    super.initState();
    _noteStreamController = StreamController<List<Map>>();
    // 初始加载数据到流中
    _loadNoteList();
  }

  // 加载数据并发送到流
  Future<void> _loadNoteList() async {
    List<Map> noteList = await sq.ReadData('SELECT * FROM notes');
    _noteStreamController.add(noteList);
  }

  @override
  void dispose() {
    // 页面销毁时关闭流,避免内存泄漏
    _noteStreamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // 执行新增笔记操作
          // await sq.InsertData(...);
          // 重新加载数据并发送到流
          await _loadNoteList();
        },
        child: const Icon(Icons.add),
      ),
      body: StreamBuilder<List<Map>>(
        stream: _noteStreamController.stream,
        builder: (context, AsyncSnapshot<List<Map>> snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                return Container(
                  height: 50,
                  child: Card(
                    child: Text('${snapshot.data![index]['note']}'),
                  ),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Text('加载失败:${snapshot.error}');
          } else {
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

进阶方案:利用sqflite的监听功能(如果使用sqflite)

sqflite库支持通过watch方法监听查询结果的变化,自动返回Stream,无需手动触发刷新:

修改数据库查询方法为返回Stream:

Stream<List<Map>> watchNoteList() async* {
  Database? db = await getdb();
  // 使用sqflite的watch方法,自动监听数据变化
  yield* db!.rawQuery('SELECT * FROM notes').asStream();
}

然后直接在StreamBuilder中使用这个Stream:

StreamBuilder<List<Map>>(
  stream: sq.watchNoteList(),
  builder: (context, snapshot) {
    // 构建列表逻辑和之前一致
  },
)

这样当数据库中的notes表数据变化时,Stream会自动发送新的列表数据,StreamBuilder会自动刷新列表。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 12:10:25