firebase - 如何在 Flutter 中缓存 Firebase 数据?

标签 firebase caching flutter dart google-cloud-firestore

在我的应用程序中,我使用 Firebase 中的数据构建了一个对象列表。在 StreamBuilder 中,我检查快照是否有数据。如果没有,我将返回一个带有“正在加载...”的简单文本小部件。我的问题是,如果我转到应用程序中的另一个页面,然后再返回,您会在一瞬间看到它在屏幕中间显示“正在加载...”,这有点烦人。我很确定它正在从 Firebase 下载数据,并在我每次返回该页面时构建小部件。如果我不检查数据,它会给我一个我试图从 null 访问数据的数据。

有没有办法缓存已经下载的数据,如果 Firebase 的数据没有变化,那么只使用缓存的数据?

这是我的代码的编辑版本:

class Schedule extends StatefulWidget implements AppPage {
  final Color color = Colors.green;
  @override
  _ScheduleState createState() => _ScheduleState();
}

class _ScheduleState extends State<Schedule> {
  List<Event> events;
  List<Event> dayEvents;
  int currentDay;
  Widget itemBuilder(BuildContext context, int index) {
    // Some Code
  }
  @override
  Widget build(BuildContext context) {
    return Center(
      child: StreamBuilder(
        stream: Firestore.instance.collection('events').snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Text("Loading...");
          }
          events = new List(snapshot.data.documents.length);
          for (int i = 0; i < snapshot.data.documents.length; i++) {
            DocumentSnapshot doc = snapshot.data.documents.elementAt(i);

            events[i] = Event(
              name: doc["name"],
              start: DateTime(
                doc["startTime"].year,
                doc["startTime"].month,
                doc["startTime"].day,
                doc["startTime"].hour,
                doc["startTime"].minute,
              ),
              end: DateTime(
                doc["endTime"].year,
                doc["endTime"].month,
                doc["endTime"].day,
                doc["endTime"].hour,
                doc["endTime"].minute,
              ),
              buildingDoc: doc["location"],
              type: doc["type"],
            );
          }
          events.sort((a, b) => a.start.compareTo(b.start));
          dayEvents = events.where((Event e) {
            return e.start.day == currentDay;
          }).toList();
          return ListView.builder(
            itemBuilder: itemBuilder,
            itemCount: dayEvents.length,
          );
        },
      ),
    );
  }
}

最佳答案

您可以使用以下代码来定义要从中检索数据的源。这将在本地缓存或服务器上搜索,而不是同时搜索。它适用于所有 get()参数,无论是搜索还是文档检索。

import 'package:cloud_firestore/cloud_firestore.dart';

FirebaseFirestore.instance.collection("collection").doc("doc").get(GetOptions(source: Source.cache))
要检查搜索是否在缓存中有数据,您需要首先对缓存运行搜索,如果没有结果,则对服务器运行它。
我找到了项目 firestore_collection使用可以大大简化此过程的简洁扩展。
import 'package:cloud_firestore/cloud_firestore.dart';

// https://github.com/furkansarihan/firestore_collection/blob/master/lib/firestore_document.dart
extension FirestoreDocumentExtension on DocumentReference {
  Future<DocumentSnapshot> getSavy() async {
    try {
      DocumentSnapshot ds = await this.get(GetOptions(source: Source.cache));
      if (ds == null) return this.get(GetOptions(source: Source.server));
      return ds;
    } catch (_) {
      return this.get(GetOptions(source: Source.server));
    }
  }
}

// https://github.com/furkansarihan/firestore_collection/blob/master/lib/firestore_query.dart
extension FirestoreQueryExtension on Query {
  Future<QuerySnapshot> getSavy() async {
    try {
      QuerySnapshot qs = await this.get(GetOptions(source: Source.cache));
      if (qs.docs.isEmpty) return this.get(GetOptions(source: Source.server));
      return qs;
    } catch (_) {
      return this.get(GetOptions(source: Source.server));
    }
  }
如果添加此代码,您只需更改 .get()文档和查询命令到 .getSavy()并且会自动先尝试缓存,只有在本地找不到数据时才联系服务器。
FirebaseFirestore.instance.collection("collection").doc("doc").getSavy();

关于firebase - 如何在 Flutter 中缓存 Firebase 数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57386003/

相关文章:

c# - MVC OutputCaching 是否优先于设置缓存响应 header ?

database - 如何在 flutter 朔迷离的Cloud Firestore中获取当前自动生成的文档ID?

android - 使用 firebase 向所有用户发送推送通知

firebase - 为什么我的 PWA 不能在 Safari 和 Opera 上运行?它显示 "can' t 建立到服务器的安全连接”

ruby-on-rails - Rails caches_page :index in Wrong Location

caching - 处理器如何获取缓存行?

flutter - 未处理的异常:customDropDown ValueChanged上的堆栈溢出

flutter - 如何检查是否为 dart 中的类定义了 getter?

swift - 何时在 tableView 单元格中分离 firebase 监听器?

android - 如何从 firebase 获取特定子数据