如何使用 Flutter 防御性地从 Firestore 请求数据
Posted
技术标签:
【中文标题】如何使用 Flutter 防御性地从 Firestore 请求数据【英文标题】:How to request data from Firestore defensively with Flutter 【发布时间】:2021-11-22 02:36:59 【问题描述】:由于 Firestore 是一个 NoSQL 数据库并且没有严格的类型规则和定义的文档结构,我考虑在我的 Flutter 应用中处理损坏的数据。
如果你想知道我为什么要防御性请求,即使它不是第三方 API -> 我可以想到我的应用程序由于数据损坏而崩溃的三个原因:
我通过 Firebase 控制台添加了错误的数据,例如将类型string
用于应该类型为 number
的字段(反复发生)。
我的应用程序中的一个错误将损坏的数据添加到 Firestore。
用户安装了我的应用的旧版本,无法处理新的 Firestore 数据结构。
我的要求:当请求来自 Firestore 的损坏数据时,应用程序不应崩溃,但应报告损坏的数据,以便可以在 Firestore a.s.a.p. 中修复数据。
【问题讨论】:
【参考方案1】:您如何看待以下方法?
假设我们有一个模型Movie
。
Movie
final String title;
final int releaseYear;
Movie(required this.title, required this.releaseYear);
Movie.from(Map<String, dynamic> data)
: title = data['title'],
releaseYear = data['release_year'];
命名构造函数from
解析来自DocumentSnapshot.data()
的文档数据并返回我们的模型。只要数据具有String
类型的字段title
和int
类型的字段release_year
(Firestore 中的number
),此方法就可以正常工作。
假设实际数据中缺少字段release_year
。这将使请求崩溃。因此,当前用户无法对相应电影执行任何操作,而我作为开发人员不会注意到,因为它在用户的设备上静默发生。
要解决第一个问题,我们可以使用带有后备数据的防御性解析,如下所示:data['release_year'] ?? -1
。没有发生崩溃,但我作为开发人员仍然没有注意到并且无法修复数据。
要解决此问题,我们还可以使用 Firebase Crashlytics。唯一的问题是,如果我们使用防御性解析来防止崩溃,则不会将任何日志发送到 Firebase。这就是我想出这个解决方案的原因:
final snapshot = await FirebaseFirestore.instance.collection('movies').doc('123').get();
try
return Movie.from(snapshot.data()!);
catch (e)
await FirebaseCrashlytics.instance
.recordError(e, e.stackTrace(), reason: 'data of movie $snapshot.id is corrupt');
return Movie.fromCorrupt(snapshot.data()!);
首先,应用程序尝试在没有任何回退机制的情况下解析文档数据。如果数据损坏,则会引发并捕获异常。在 catch 块中,错误被发送到 Firebase,然后调用防御性解析构造函数fromCorrupt
让用户继续使用剩余的数据在应用程序中。在fromCorrupt
中,每个字段在用于创建模型Movie
之前都检查了null 和类型。如果值为 null 或类型错误,则使用备用值。
你觉得我的方法怎么样?我是否过度设计? ?
【讨论】:
以上是关于如何使用 Flutter 防御性地从 Firestore 请求数据的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 上传列表到 Google Firestore
如何无限制地从 Cloudinary API 获取所有图像或如何使用 next_cursor?