Flutter Firebase Firestore优先读缓存再读服务器问题求助
解决方案:优先从Firestore缓存读取数据的可运行示例
你的代码核心问题是未处理缓存读取失败的异常:当本地没有Firestore缓存数据时,调用get(const GetOptions(source: Source.cache))会直接抛出FirebaseException,导致代码无法执行到读取服务器的逻辑。以下是修正后的完整可运行代码:
1. 修正后的ProgramService实现
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class Program { final String id; final String name; Program({required this.id, required this.name}); // 确保fromJson能正确解析Firestore文档数据 factory Program.fromJson(Map<String, dynamic> json) { return Program( id: json['id'] as String, name: json['name'] as String, // 根据你的实际业务字段补充解析逻辑 ); } } class ProgramService extends AsyncNotifier<List<Program>> { Future<List<Program>> _getPrograms() async { final fireStoreRef = FirebaseFirestore.instance.collection('program'); // 优先尝试从缓存读取 try { final cacheSnapshot = await fireStoreRef.get(const GetOptions(source: Source.cache)); print('数据来自缓存'); return cacheSnapshot.docs .map((doc) => Program.fromJson(doc.data())) .toList(); } on FirebaseException catch (_) { // 缓存读取失败(无缓存/缓存过期),切换到服务器读取 final serverSnapshot = await fireStoreRef.get(const GetOptions(source: Source.server)); print('数据来自服务器'); return serverSnapshot.docs .map((doc) => Program.fromJson(doc.data())) .toList(); } } @override Future<List<Program>> build() async { return _getPrograms(); } } final asyncProgramProvider = AsyncNotifierProvider<ProgramService, List<Program>>(() { return ProgramService(); });
2. UI层使用Provider的示例
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class ProgramListPage extends ConsumerWidget { const ProgramListPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final programsState = ref.watch(asyncProgramProvider); return Scaffold( appBar: AppBar(title: const Text('节目列表')), body: programsState.when( loading: () => const Center(child: CircularProgressIndicator()), error: (err, stack) => Center(child: Text('加载失败: $err')), data: (programs) { if (programs.isEmpty) { return const Center(child: Text('暂无节目数据')); } return ListView.builder( itemCount: programs.length, itemBuilder: (context, index) { final program = programs[index]; return ListTile( title: Text(program.name), subtitle: Text(program.id), ); }, ); }, ), ); } }
关键修正点说明
- 增加
try-catch捕获缓存读取的异常:当本地无缓存时,Firestore会抛出异常,此时自动切换到服务器请求。 - 确保
Program.fromJson与Firestore文档字段匹配:如果字段不对应,会导致解析失败,需根据你的实际数据结构调整。 - 保留日志打印,方便验证数据来源。
内容的提问来源于stack exchange,提问作者Fynn Gerdes
相关产品推荐
相关产品推荐

