我正在尝试从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()
。
我在FireStore数据库中有一个集合carpools
,其中有一些记录。
我已将Firestore数据库规则设置为允许所有规则。
rules_version = '2';
service cloud.firestore {
match /** {
allow read, write: if true;
}
}
编辑:我的Firebase身份验证有效。 (如果有帮助)
这里可能缺少什么?
答案 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";
}
要使用安全规则,下面的链接会有所帮助
答案 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
至少满足了一次,这使您认为自己正在永久等待。