Firestore ConnectionState在Flutter应用中永远处于等待状态

时间:2019-09-01 07:40:50

标签: firebase flutter google-cloud-firestore firebase-security

我正在尝试从Firestore数据库中获取记录,并将其显示在Flutter应用中。

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text('Hello'),
          actions: <Widget>[
            IconButton(icon: Icon(Icons.list), onPressed: _pushSaved)
          ]),
      drawer: _buildDrawer(),
      body: _buildCarpoolsList(),
    );
  }

Widget _buildCarpoolsList() {
    return StreamBuilder<QuerySnapshot>(
        stream: Firestore.instance.collection("carpools").snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return CircularProgressIndicator();
          } else {
            var _carpools = snapshot.data.documents;
            return ListView(
                padding: const EdgeInsets.all(16.0),
                children: _deserializeCarpools(_carpools));
          }
        });
  }

_buildCarpoolsList()函数中,snapshot.ConnectionState始终为ConnectionState.waiting,该函数返回CircularProgressBar()ConnectionState.waiting

我在FireStore数据库中有一个集合carpools,其中有一些记录。

我已将Firestore数据库规则设置为允许所有规则。

rules_version = '2';
service cloud.firestore {
  match /** {
      allow read, write: if true;
  }
}

编辑:我的Firebase身份验证有效。 (如果有帮助)

这里可能缺少什么?

5 个答案:

答案 0 :(得分:1)

您可以在Firebase控制台中修改安全设置。 如果您在生产模式下创建数据库(而非测试),则数据库附带安全规则,这些规则可能会阻止任何连接,直到您允许。

在数据库屏幕中打开Rules标签,(仅测试->允许读写,如下所示) 如果可行,只需考虑阅读安全规则并根据需要进行适当设置。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

答案 1 :(得分:0)

是否在GoogleService-Info.plist中添加了Runner.xcworkspace,必须使用Xcode打开它。我总是忘记将其添加到新项目中:

答案 2 :(得分:0)

我遇到了同样的情况。使用cloud_firestore插件和StreamBuilder:

class DealerWorkPage extends StatelessWidget {
final String wheelId;
DealerWorkPage(this.wheelId);
@override
Widget build(BuildContext context) {
return StreamBuilder(
    stream: Firestore.instance.collection('wheels').document(this.wheelId).snapshots(),

    builder: (context, asyncSnapshot) {
        if(asyncSnapshot.hasError) return Text('Error: ${asyncSnapshot.error}');

        switch (asyncSnapshot.connectionState) {
          case ConnectionState.none: return Center(child: Text('No data'));
          case ConnectionState.waiting: return Center(child: CircularProgressIndicator());
          case ConnectionState.active:
            return Center(child: Text(asyncSnapshot["description"]))
          break;
        }
        return null;
    });
 }
}

此代码运行没有错误,但仅永久显示CircularProgressIndicator()!

我尝试了另一个带有add子句的flutter项目:

await _firestore.collection('messages').add({
    'text': messageController.text,
    'from': widget.user.email,
    'date': DateTime.now().toIso8601String().toString(),
  });

它抛出:PlatformException(执行setData时出错,PERMISSION_DENIED:权限丢失或不足

现在,就像@MSaudi所说的那样,此错误与firebase安全规则有关。然后,我在Firebase控制台中检查数据库安全规则。是的,我忘记了“延长”数据库访问的日期:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {

// This rule allows anyone on the internet to view, edit, and delete
// all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// your app will lose access to your Firestore database
match /{document=**} {
  allow read, write: if request.time < timestamp.date(2020, 1, 27);
  }
 }
}

在将request.time timestamp.date(2020,1,27)更改为以后的日期之后, VOILA!我的StreamBuilder的行为符合预期!永远不再等待! 希望这些信息对您有所帮助。

答案 3 :(得分:0)

我也遇到了同样的问题,我一直关注Flutter的指南。状态始终处于连接状态,没有数据返回,也没有错误。这是在iOS中,然后我在Android中运行了该应用程序,幸运的是在LogCat中,我看到了一条消息permission to listen to query was denied 默认情况下,安全规则似乎拒绝一切。必须允许它@MSaudi提到。我添加了它,就可以了

   match /{collectionName}/{documentId} {
       allow read, write : if collectionName == "products";
   }

要使用安全规则,下面的链接会有所帮助

Firebase security rules

答案 4 :(得分:0)

如果您在FlutterFire上检查了Cloud Firestore,并且安全规则没有问题,请检查您是否正确使用.map().forEach()

例如,以下方法运行良好:

builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

        List<String> urls = [];
        if (snapshot.hasError) {
          return ...
        }

        if (snapshot.connectionState == ConnectionState.waiting) {
          return ...
        }
        
        **snapshot.data.docs.forEach((QueryDocumentSnapshot document) {
          print(document);
          urls.add(...);
        });**

        return Container( 
          child: GridView.count(
            crossAxisCount: ...,
            childAspectRatio: (...),
            children: List.generate(urls.length, (index) {

但是,如果您的小部件应该使用urls中的项目显示一些图像,则以下示例不执行任何操作:

builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

        List<String> urls = [];
        if (snapshot.hasError) {
          return ...
        }

        if (snapshot.connectionState == ConnectionState.waiting) {
          return ...
        }
        
        
        **snapshot.data.docs.map((QueryDocumentSnapshot document) {
          print(document);
          urls.add(...);
        });**

        return Container( 
          child: GridView.count(
            crossAxisCount: ...,
            childAspectRatio: (...),
            children: List.generate(urls.length, (index) {

尽管在两个示例中都打印了document,但这并不意味着它们执行相同的操作。还值得注意的是,在加载过程中,条件snapshot.connectionState == ConnectionState.waiting至少满足了一次,这使您认为自己正在永久等待。