我的带有 Firestore 的 Flutter 应用在​​从 Android 后台恢复时遇到非常慢的查询

Art*_*ght 6 firebase flutter google-cloud-firestore

使用颤振 1.20.2。

我的 Flutter 应用使用 Firestore 作为后端数据库。对于我正在使用的当前版本以及在此移动应用程序的整个开发过程中,我注意到如果我的应用程序在后台运行一段时间(可能是几分钟),那么当我将应用程序带回前台时,查询返回数据非常慢。这不会发生在 iOS 上。它只发生在 Android 上。

当我的应用忙于从 Firestore 检索数据时,我使用 CircularProgressIndicators。我正在使用固态管理设置,其中我的每个视图都有一个扩展 BaseModel 的模型:

class BaseModel extends ChangeNotifier {
  ViewState _state = ViewState.Idle;
  ViewState get state => _state;
  bool isDisposed = false;

  void setState(ViewState viewState) {
    _state = viewState;
    if (!isDisposed) {
      notifyListeners();
    }
  }

  @override
  void dispose() {
    isDisposed = true;
    super.dispose();
  }
}
Run Code Online (Sandbox Code Playgroud)

我的视图然后以以下方式使用我的视图特定模型:

  @override
  Widget build(BuildContext context) {
    return BaseView<MyProfileModel>(
        //onModelReady: (model) => model.initialise(Provider.of<User>(context, listen: false)),
        onModelReady: (model) => model.initialise(),
        builder: (context, model, child) => Scaffold(
              resizeToAvoidBottomInset: false,
...
Run Code Online (Sandbox Code Playgroud)

当应用程序在后台或从后台恢复时,我还没有使用 AppLifecycleState 类来做任何特殊的事情。

当我的模型忙于检索数据时,我会显示忙碌的循环进度指示器。

问题是,当我从后台恢复我的应用程序到前台时,有时该应用程序在检索数据之前可能会忙碌长达 1 分钟 - 但只有在第一次回到前台之后。之后的所有调用都是正常的。有时,它甚至会在回到前台后第一次尝试获取数据时挂起。

我觉得我没有实施与将应用程序恢复到使用 Firestore 数据库的前台相关的最佳实践。我怀疑它与重新建立 Firestore 连接和/或本地缓存有关。我的应用程序使用这些的默认设置。

我所有的 Firestore API 调用都包含在它自己的类中,我每次都以相同的方式调用它:

    await Firestore.instance
        .collection(DBStrings.COLLECTION_AD_MESSAGES)
        .document(ad.adId)
        .collection(DBStrings.COLLECTION_CHILD_AD_MESSAGES)
        .document()
        .setData({
        // Set fields...
    }).catchError((e) {
      res = false;
    });
Run Code Online (Sandbox Code Playgroud)

有人可以让我深入了解这个问题以及可能导致它的原因吗?

Rod*_*Rod 2

在我看来,您的应用程序正在失去连接,并且检索到的数据来自缓存。我的建议是,当您的应用程序处于后台时,尝试从 Firebase 控制台更改后端数据,然后测试检索到的数据是更新的还是旧的。

如果数据是旧的,则意味着您的应用程序无法恢复连接。要解决此问题,您需要检查身份验证状态(如果使用)并检查连接状态。识别连接状态并不允许应用程序在进入缓存之前花费很长时间的一个简单方法是强制应用程序从远程请求数据并提供超时,如下所示:

QuerySnapshot snapshot = await query.getDocuments(source: Source.server).timeout(
        _timeoutDuration,
        // this or any other callback to handle timeout
        onTimeout: () => query.getDocuments(source: Source.cache));
Run Code Online (Sandbox Code Playgroud)

如果您正在使用身份验证,您可以通过调用以下命令来检查身份验证状态:

FirebaseUser currentUser = await _auth.currentUser();
if (currentUser != null) {
  // Handle your auth problem here
}
Run Code Online (Sandbox Code Playgroud)

如果您不使用身份验证,并且应用程序在这么长时间后从服务器检索数据,请检查应用程序是否会在没有 firebase 查询的情况下更快地返回。