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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:45:30