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
相关产品推荐
相关产品推荐

