Flutter Riverpod实现:每5秒重复调用API并更新界面
解决方案:实现Riverpod定时刷新API数据
1. 为FutureProvider添加定时刷新逻辑
在dataProvider中,通过Timer.periodic实现每5秒触发一次数据刷新,同时利用ref.onDispose清理定时器避免内存泄漏:
final dataProvider = FutureProvider<String>((ref) async { // 每5秒触发一次Provider刷新 final timer = Timer.periodic(const Duration(seconds: 5), (_) { ref.invalidateSelf(); // 触发Provider重新执行数据获取逻辑 }); // 当Provider不再被监听时,销毁定时器 ref.onDispose(() => timer.cancel()); // 调用API获取数据 return ref.watch(dataService).getData(); });
2. 优化UI层的异步状态处理
原代码直接将异步结果转为字符串显示,无法区分加载、错误、成功状态,建议用AsyncValue.when方法处理不同状态:
class MyExampleApp extends ConsumerWidget { const MyExampleApp({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final dataAsync = ref.watch(dataProvider); return MaterialApp( home: Scaffold( body: Center( child: dataAsync.when( loading: () => const CircularProgressIndicator(), // 加载中显示进度条 error: (error, _) => Text('加载失败: $error'), // 错误状态显示错误信息 data: (data) => Text(data), // 成功状态显示数据 ), ), ), ); } }
3. 可选优化:返回结构化数据(推荐)
原getData方法返回字符串,建议解析为结构化模型,让UI层更易处理:
// 定义Post数据模型 class Post { final int userId; final int id; final String title; final String body; Post({required this.userId, required this.id, required this.title, required this.body}); factory Post.fromJson(Map<String, dynamic> json) { return Post( userId: json['userId'], id: json['id'], title: json['title'], body: json['body'], ); } } // 修改DataService的getData方法 class DataService { final Dio _dio = Dio(); Future<List<Post>> getData() async { try { final response = await _dio.get("https://jsonplaceholder.typicode.com/posts"); return (response.data as List).map((json) => Post.fromJson(json)).toList(); } on SocketException { throw Exception("网络连接异常"); } catch (e) { throw Exception(e.toString()); } } } // 更新Provider泛型类型 final dataProvider = FutureProvider<List<Post>>((ref) async { final timer = Timer.periodic(const Duration(seconds: 5), (_) { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return ref.watch(dataService).getData(); }); // UI层改为列表展示 data: (posts) => ListView.builder( itemCount: posts.length, itemBuilder: (context, index) { final post = posts[index]; return ListTile( title: Text(post.title), subtitle: Text(post.body), ); }, ),
核心逻辑说明
ref.invalidateSelf():触发FutureProvider重新执行数据获取逻辑,从而拉取最新数据。ref.onDispose:确保组件销毁时定时器被取消,避免内存泄漏。AsyncValue.when:统一处理异步状态的三种场景,提升用户体验。
内容的提问来源于stack exchange,提问作者DongPhamBK
相关产品推荐
相关产品推荐

