flutter - 使用 StreamBuilder 代替 FeatureBuilder 来避免 Firestore 中的 whereIn 10 限制
问题描述
我想获取特定用户喜欢的帖子并在交错网格视图中显示它们。我可以在 FutureBuilder 中做到这一点。但是在 FutureBuilder 中,由于whereIn
10 的限制,我无法获取更多。我知道它可以使用 StreamBuilder 来实现。但我很无奈,不知道该怎么做。
这是我的 Firebase 收藏。
下面是获取数据的代码:
final FirebaseFirestore firestore = FirebaseFirestore.instance;
getData() async {
SharedPreferences sp = await SharedPreferences.getInstance();
String _uid = sp.getString('uid');
final DocumentReference ref = firestore.collection('users').doc(_uid);
DocumentSnapshot snap = await ref.get();
List d = snap['loved items'];
List filteredData = [];
if (d.isNotEmpty) {
await firestore
.collection('contents')
.where('timestamp', whereIn: d)
.get()
.then((QuerySnapshot snap) {
filteredData = snap.docs;
});
}
notifyListeners();
return filteredData;
}
这是 FutureBuilder 代码:
body: sb.guestUser == true
? EmptyPage(
icon: FontAwesomeIcons.heart,
title: 'No wallpapers found.\n Sign in to access this feature',
)
: FutureBuilder(
future: context.watch<BookmarkBloc>().getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.length == 0)
return EmptyPage(
icon: FontAwesomeIcons.heart,
title: 'No wallpapers found',
);
return _buildList(snapshot);
} else if (snapshot.hasError) {
return Center(
child: Text(snapshot.error),
);
}
return Center(
child: CupertinoActivityIndicator(),
);
},
),
),
);
}
Widget _buildList(snapshot) {
return StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
List d = snapshot.data;
return InkWell(
child: Stack(
children: <Widget>[
Hero(
tag: 'bookmark$index',
child: cachedImage(d[index]['image url'])),
Positioned(
bottom: 15,
left: 12,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
d[index]['category'],
style: TextStyle(color: Colors.white, fontSize: 18),
)
],
),
),
Positioned(
right: 10,
top: 20,
child: Row(
children: [
Icon(Icons.favorite,
color: Colors.white.withOpacity(0.5), size: 25),
Text(
d[index]['loves'].toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.7),
fontSize: 16,
fontWeight: FontWeight.w600),
),
],
),
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage(
tag: 'bookmark$index',
imageUrl: d[index]['image url'],
catagory: d[index]['category'],
timestamp: d[index]['timestamp'],
)));
},
);
},
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(2, index.isEven ? 4 : 3),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
padding: EdgeInsets.all(15),
);
}
}
我提到了互联网,但我并不完全知道如何将 FutureBuilder 转换为返回快照列表的 StreamBuilder。还有其他方法吗?
解决方案
首先,“ whereIn
10 的限制”是 Firestore 的硬约束。这意味着无论您使用FutureBuilder
或StreamBuilder
,限制 10 的约束仍然适用。
现在,如果您仍想切换到StreamBuilder
StreamBuilder<QuerySnapshot>(
stream: _yourStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
您需要调整它以成为 Stream
await firestore
.collection('contents')
.where('timestamp', whereIn: d)
.get()
.then((QuerySnapshot snap) {
filteredData = snap.docs;
});
您需要更改.get( )
为.snapshots()
并需要使用snapshot.data.docs.map
此处的流示例中的更多详细信息https://firebase.flutter.dev/docs/firestore/usage
编辑:
关于 10 项硬约束:根据您的具体项目,您可以:
多次查询然后在您的应用程序中本地合并(同时删除重复项),或
另一种解决方案是在您的应用程序中做一些过滤客户端(基本上,从 FireStore 带来更多并在颤振中过滤),或者
另一种解决方案是创建由其他字段组合的新字段(例如,在您的情况下,它可能是“月”或“周数”,因此您在 1 个条件下有一周的时间而不是 7 天)
推荐阅读
- ampscript - 通过 AMPscript 在电子邮件中显示当前年份
- docker - 在 Docker 中的挂载文件夹中访问
- c# - 通过 rotativa 在本地获取 PDF 时,为什么我不能通过在线下载 PDF?
- gluon - 有没有办法使用胶子地图进行导航或方向?
- c# - 更改脚本的一个属性值,使其影响该脚本附加到的所有游戏对象
- excel - 从 Excel 通过 Outlook 发送邮件
- spring-boot - spring boot 2.1.x 是否支持 yaml 1.2 规范
- macos - 如何在mac中获得鼠标下的顶部窗口
- angular - 如何测试跨度的幻影?
- angular - 在 ngFor 选择选项中,如何在 onChange 发送特定对象属性的值