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

如何通过Stream定期刷新Flutter数据?将Future请求改造为每5秒动态更新的实现方案

嘿,我来帮你把这个Future改成支持定时自动刷新的Stream,这样就能实现每5秒更新一次货币数据啦!咱们分几步来改:

第一步:改造数据获取逻辑,创建定时Stream

在你存放_fetchCurrency的文件里,新增一个返回Stream的方法,用它来包装你的异步请求,实现每5秒触发一次:

// 保留你原有的_fetchCurrency方法,这是实际拉取数据的核心逻辑
Future<List<CurrencyModel>?> _fetchCurrency() async {
  currencyList = [];
  final response = await http.get(
    Uri.parse('https:...'), // 你的API地址
  );
  if (response.statusCode == 200) {
    List<dynamic> values = json.decode(response.body);
    if (values.isNotEmpty) {
      for (int i = 0; i < values.length; i++) {
        if (values[i] != null) {
          Map<String, dynamic> map = values[i];
          currencyList.add(CurrencyModel.fromJson(map));
        }
      }
    }
    return currencyList;
  } else {
    throw Exception('Failed to load currencies');
  }
}

// 新增:创建一个每隔5秒自动拉取数据的Stream
Stream<List<CurrencyModel>?> getCurrencyStream() {
  // Stream.periodic会按指定间隔发送事件,我们忽略事件本身,每次调用_fetchCurrency
  return Stream.periodic(const Duration(seconds: 5), (_) => _fetchCurrency())
      .asyncMap((future) => future); // 把Future转换成Stream的元素
}

第二步:修改主页面,用StreamBuilder替换FutureBuilder

在主页面的State类里,我们需要初始化Stream,然后把原来的FutureBuilder换成StreamBuilder:

class _YourPageState extends State<YourPage> {
  late Stream<List<CurrencyModel>?> _currencyStream;
  StreamSubscription? _streamSubscription; // 用来管理流的订阅,防止内存泄漏

  @override
  void initState() {
    super.initState();
    // 如果你想页面一打开就自动刷新,就初始化流;如果想通过按钮启动,就把这行移到startTimer里
    // _currencyStream = client.getCurrencyStream();
    // _streamSubscription = _currencyStream.listen((_) {});
  }

  void startTimer() {
    setState(() {
      // 启动流(如果之前有订阅,先取消再重新订阅)
      _streamSubscription?.cancel();
      _currencyStream = client.getCurrencyStream();
      _streamSubscription = _currencyStream.listen((_) {});
    });
  }

  @override
  void dispose() {
    // 页面销毁时一定要取消订阅,避免内存泄漏
    _streamSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Currencies'),
        centerTitle: true,
      ),
      body: StreamBuilder<List<CurrencyModel>?>(
        stream: _currencyStream,
        initialData: null, // 初始状态显示加载中
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            // 这里不要用全局的currencyList,直接用snapshot.data!
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) => CurrencyCard(
                snapshot.data![index],
              ),
            );
          } else if (snapshot.hasError) {
            return Text('${snapshot.error}');
          }
          return const Center(child: CircularProgressIndicator());
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: startTimer,
        child: const Icon(Icons.update_sharp),
      ),
    );
  }
}

几个关键注意点:

  • 不要依赖全局的currencyList:尽量用StreamBuilder的snapshot.data来获取最新数据,避免全局变量导致的数据不同步问题。
  • 取消流订阅:在页面销毁时一定要调用_streamSubscription?.cancel(),不然会造成内存泄漏。
  • API频率限制:如果你的目标API有请求频率限制,要确认5秒一次的调用不会触发限流,必要时可以调整间隔时间。

这样改完之后,点击浮动按钮就能启动定时刷新,每5秒自动拉取最新的货币数据并更新UI啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:57:49