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

Flutter如何每隔n分钟调用API并实现跨页面数据同步更新

实现全局定时拉取API+数据共享+自动刷新方案

原有代码问题

你当前的写法存在两个核心问题:

  • FutureBuilder仅会在首次渲染时绑定初始传入的Future引用,后续你在main函数里重新给someFuture赋值时,没有触发组件的状态更新,FutureBuilder感知不到Future变化,不会自动重建
  • 直接在main函数中创建流订阅没有绑定生命周期,应用退出时订阅无法自动取消,存在内存泄漏风险

由于项目未引入状态管理工具,直接使用Flutter原生提供的InheritedWidget+ValueNotifier+顶层StatefulWidget即可实现需求,不需要任何第三方依赖。


具体实现步骤

1. 编写顶层全局数据共享组件

这个组件包裹整个应用,统一管理定时拉取逻辑、共享数据、生命周期:

import 'dart:async';
import 'package:flutter/material.dart';

// 替换成你自己的业务实体类
typedef SomeObject = dynamic;
// 你原有拉取数据的方法
List<SomeObject> someFunction() => [];

class AppApiScope extends StatefulWidget {
  final Widget child;
  const AppApiScope({super.key, required this.child});

  // 提供of方法,方便子树任意页面获取共享状态
  static AppApiScopeState of(BuildContext context) {
    final state = context.findAncestorStateOfType<AppApiScopeState>();
    assert(state != null, '请确保AppApiScope在组件树顶层');
    return state!;
  }

  @override
  State<AppApiScope> createState() => AppApiScopeState();
}

class AppApiScopeState extends State<AppApiScope> {
  StreamSubscription? _periodicSub;
  // 持有最新的拉取Future,值变化时自动通知所有监听者
  late final ValueNotifier<Future<List<SomeObject>>?> latestDataFuture;

  @override
  void initState() {
    super.initState();
    // 应用启动时先拉取一次数据,避免首次加载等待一个周期
    latestDataFuture = ValueNotifier(_fetchApiData());
    // 启动定时任务,需要n分钟间隔就把Duration改成Duration(minutes: n)
    _periodicSub = Stream.periodic(const Duration(seconds: 10)).listen((_) {
      latestDataFuture.value = _fetchApiData();
    });
  }

  // 统一的API拉取逻辑
  Future<List<SomeObject>> _fetchApiData() async {
    await Future.delayed(const Duration(milliseconds: 500));
    return someFunction();
  }

  // 提供全局手动刷新方法,任意页面都可以调用
  void manualRefresh() {
    latestDataFuture.value = _fetchApiData();
  }

  @override
  void dispose() {
    // 销毁时释放所有资源,避免内存泄漏
    _periodicSub?.cancel();
    latestDataFuture.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => widget.child;
}

2. 修改main函数,在应用最外层注入共享组件

void main() {
  runApp(
    AppApiScope(
      child: const MyApp(),
    ),
  );
}

3. 修改首页FutureBuilder代码,监听数据变化自动重建

通过ValueListenableBuilder监听顶层共享的Future变化,每次定时任务拉取新数据时,会自动传入最新的Future给FutureBuilder,触发重建:

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final apiScope = AppApiScope.of(context);
    return Scaffold(
      appBar: AppBar(title: const Text('首页')),
      body: ValueListenableBuilder<Future<List<SomeObject>>?>(
        valueListenable: apiScope.latestDataFuture,
        builder: (context, activeFuture, _) {
          return FutureBuilder<List<SomeObject>>(
            future: activeFuture,
            builder: (context, snapshot) {
              // 加载状态
              if (snapshot.connectionState != ConnectionState.done) {
                return const Center(child: CircularProgressIndicator());
              }
              // 错误状态
              if (snapshot.hasError) {
                return Center(child: Text('加载失败:${snapshot.error}'));
              }
              // 正常数据展示
              final dataList = snapshot.data ?? [];
              return ListView.builder(
                itemCount: dataList.length,
                itemBuilder: (context, index) => ListTile(
                  title: Text(dataList[index].toString()),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

方案特性

  • 全应用仅存在一个定时拉取实例,不会重复发起无效请求
  • 任意子页面都可以通过AppApiScope.of(context)获取共享数据、调用手动刷新方法,实现全页面数据互通
  • 所有资源释放绑定应用生命周期,无内存泄漏风险
  • 完全基于Flutter原生能力实现,不需要引入任何第三方状态管理依赖

内容的提问来源于stack exchange,提问作者who-aditya-nawandar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:57:22