Flutter中FutureBuilder和StreamBuilder

发布于:2025-06-21 ⋅ 阅读:(14) ⋅ 点赞:(0)

在 Flutter 中,如果你想让 FutureBuilderfuture 函数再次执行,可以通过以下几种方式实现:


方法 1:使用 Key 强制重建 FutureBuilder

通过改变 FutureBuilderkey,可以强制 Flutter 重建它,从而重新执行 future 函数:

class MyWidget extends StatefulWidget {
  
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  // 使用 UniqueKey 来强制重建 FutureBuilder
  UniqueKey _futureBuilderKey = UniqueKey();

  Future<String> fetchData() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    return "New Data: ${DateTime.now()}";
  }

  void _refreshData() {
    setState(() {
      // 改变 key,FutureBuilder 会重新执行 future
      _futureBuilderKey = UniqueKey();
    });
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: _refreshData,
          child: Text("Refresh Data"),
        ),
        FutureBuilder<String>(
          key: _futureBuilderKey, // 关键点:改变 key 会重建 FutureBuilder
          future: fetchData(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            }
            if (snapshot.hasError) {
              return Text("Error: ${snapshot.error}");
            }
            return Text("Data: ${snapshot.data}");
          },
        ),
      ],
    );
  }
}

方法 2:使用 StatefulWidget 管理 future

StatefulWidget 中存储 future,并在需要刷新时重新调用 fetchData

class MyWidget extends StatefulWidget {
  
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  Future<String>? _futureData;

  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 2));
    return "New Data: ${DateTime.now()}";
  }

  
  void initState() {
    super.initState();
    _futureData = fetchData(); // 初始化 future
  }

  void _refreshData() {
    setState(() {
      _futureData = fetchData(); // 重新赋值 future
    });
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: _refreshData,
          child: Text("Refresh Data"),
        ),
        FutureBuilder<String>(
          future: _futureData,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            }
            if (snapshot.hasError) {
              return Text("Error: ${snapshot.error}");
            }
            return Text("Data: ${snapshot.data}");
          },
        ),
      ],
    );
  }
}

方法 3:使用 StreamBuilder 替代 FutureBuilder

如果数据需要频繁刷新,可以考虑使用 Stream + StreamBuilder

class MyWidget extends StatefulWidget {
  
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final StreamController<String> _streamController = StreamController();

  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 2));
    return "New Data: ${DateTime.now()}";
  }

  void _refreshData() {
    fetchData().then((data) {
      _streamController.add(data); // 手动推送新数据到 Stream
    });
  }

  
  void initState() {
    super.initState();
    _refreshData(); // 初始化数据
  }

  
  void dispose() {
    _streamController.close();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: _refreshData,
          child: Text("Refresh Data"),
        ),
        StreamBuilder<String>(
          stream: _streamController.stream,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            }
            if (snapshot.hasError) {
              return Text("Error: ${snapshot.error}");
            }
            return Text("Data: ${snapshot.data}");
          },
        ),
      ],
    );
  }
}

总结

方法 适用场景 特点
改变 Key 简单场景 强制重建 FutureBuilder,适合一次性刷新
重新赋值 future 推荐方式 通过 setState 更新 future,逻辑清晰
StreamBuilder 频繁刷新 适合需要持续监听数据变化的场景

选择最适合你需求的方式即可!


网站公告

今日签到

点亮在社区的每一天
去签到