StreamBuilder 的 Firebase 查询立即出现和消失
StreamBuilder's Firebase query appears and disappears instantly
我正在尝试查询一个 Stream 文档应该在 'unit[= 中包含 'UretimKurulum' 34=]”数组和“日期”应该等于或大于今天的日期。
在流式传输此查询时,我确实在几秒钟内得到了我想要的正确结果,然后显示 'No Data Available'。
下面是实际代码:
final FirebaseFirestore _db = FirebaseFirestore.instance;
final DateTime _now = DateTime.now();
final String val = 'UretimKurulum';
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot<Object>>(
stream: _db.collection('Schedule').where('date', isGreaterThanOrEqualTo: _now).where('unit', arrayContains: val).snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: LinearProgressIndicator());
} else {
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
} else {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);
}
}
},
);
}
}
如果我尝试删除:
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
}
我收到以下错误:
════════ Exception caught by widgets library ═══════════════════════════════════
The following TypeErrorImpl was thrown building StreamBuilder<QuerySnapshot<Object>>(dirty, state: _StreamBuilderBaseState<QuerySnapshot<Object>, AsyncSnapshot<QuerySnapshot<Object>>>#0508a):
Unexpected null value.
当您还没有在 Firestore 中创建必要的索引时,您会眨眼。您需要为涉及 >、>=、<、<= 的任何查询创建索引。在你的情况下,你的 firestore.indexes.json:
中应该有类似下面的内容
{
"collectionGroup": "Schedule",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "unit",
"arrayConfig": "CONTAINS"
},
{
"fieldPath": "date",
"order": "ASCENDING"
}
]
},
或者,如果您愿意,也可以从 Firestore 控制台手动执行。
第一件事
//instead of DateTime
final DateTime _now = DateTime.now();
//you should use Timestamp which is provided by Firebase Firestore
final Timestamp timeNow = Timestamp.now();
第二件事
//instead of
where('unit', arrayContains: val)
//try this
where("unit", "arrayContains", val)
希望它能工作如果没有那么回复我我会尝试找到其他解决方案。
正如@blaneyneil 和我自己之前所说,确实这是一个索引问题。
解决方案是从 Firebase 控制台创建一个复合集合索引,并将字段 'todoUnit' 索引为数组,将 'date' 索引为升序。
- 为什么要尝试删除校验数据?,如果数据为 null 或为空,则一般标准中的 UX 应该不显示任何数据。为避免空值,您可以使用 elvis 运算符,例如
data ?? 'default-data'
或 data == null ? 'no-data' : 'found-data'
- 适合日期时间条件的是使用
DateTime.now().microsecondsSinceEpoch
而不是 DateTime.now()
这个可选但更精确的数据是有效的 https://docs.w3cub.com/dart~2/dart-core/datetime/microsecondssinceepoch
- 你可以尝试改变
// instead of
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
} else {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);
}
// try this
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);
我正在尝试查询一个 Stream 文档应该在 'unit[= 中包含 'UretimKurulum' 34=]”数组和“日期”应该等于或大于今天的日期。
在流式传输此查询时,我确实在几秒钟内得到了我想要的正确结果,然后显示 'No Data Available'。
下面是实际代码:
final FirebaseFirestore _db = FirebaseFirestore.instance;
final DateTime _now = DateTime.now();
final String val = 'UretimKurulum';
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot<Object>>(
stream: _db.collection('Schedule').where('date', isGreaterThanOrEqualTo: _now).where('unit', arrayContains: val).snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: LinearProgressIndicator());
} else {
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
} else {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);
}
}
},
);
}
}
如果我尝试删除:
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
}
我收到以下错误:
════════ Exception caught by widgets library ═══════════════════════════════════
The following TypeErrorImpl was thrown building StreamBuilder<QuerySnapshot<Object>>(dirty, state: _StreamBuilderBaseState<QuerySnapshot<Object>, AsyncSnapshot<QuerySnapshot<Object>>>#0508a):
Unexpected null value.
当您还没有在 Firestore 中创建必要的索引时,您会眨眼。您需要为涉及 >、>=、<、<= 的任何查询创建索引。在你的情况下,你的 firestore.indexes.json:
中应该有类似下面的内容{
"collectionGroup": "Schedule",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "unit",
"arrayConfig": "CONTAINS"
},
{
"fieldPath": "date",
"order": "ASCENDING"
}
]
},
或者,如果您愿意,也可以从 Firestore 控制台手动执行。
第一件事
//instead of DateTime
final DateTime _now = DateTime.now();
//you should use Timestamp which is provided by Firebase Firestore
final Timestamp timeNow = Timestamp.now();
第二件事
//instead of
where('unit', arrayContains: val)
//try this
where("unit", "arrayContains", val)
希望它能工作如果没有那么回复我我会尝试找到其他解决方案。
正如@blaneyneil 和我自己之前所说,确实这是一个索引问题。
解决方案是从 Firebase 控制台创建一个复合集合索引,并将字段 'todoUnit' 索引为数组,将 'date' 索引为升序。
- 为什么要尝试删除校验数据?,如果数据为 null 或为空,则一般标准中的 UX 应该不显示任何数据。为避免空值,您可以使用 elvis 运算符,例如
data ?? 'default-data'
或data == null ? 'no-data' : 'found-data'
- 适合日期时间条件的是使用
DateTime.now().microsecondsSinceEpoch
而不是DateTime.now()
这个可选但更精确的数据是有效的 https://docs.w3cub.com/dart~2/dart-core/datetime/microsecondssinceepoch - 你可以尝试改变
// instead of
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
} else {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);
}
// try this
if (!snapshot.hasData) {
return Center(child: Text('No Data Available'));
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var docSnap = snapshot.data!.docs[index];
return Text(docSnap.id);
},
);