flutter - 输入'未来' 不是类型 'Stream 的子类型' 从 Firebase 获取数据
问题描述
我正在从 Firebase 存储和 Firestore 中检索数据,以在列表中显示带有图标(如果项目是文件)或图像(如果是图像)的项目。问题是,如果我一次获得所有图像,它不会全部加载。它最多加载 20 个并且由于内存泄漏而崩溃。所以我的想法是做一个按时间获取 10 个元素的列表,当用户向下滚动到结果的底部时,它会加载更多的 10 个元素并随后加载。但是,我正在使用 Future builder 并且我无法在需要时更新列表并且问题仍然存在,所以现在,我试图进入一个流并使用 StreamBuilder 显示以便能够动态更新列表。
这是我的控制器:
loadList(String submenu, [int limit]) async {
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
List<ItemLab> conteudo = [];
if(subPathSlashless.isEmpty || subPathSlashless == null){
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
});
}
for(int i = 0; i < retorno.items.length ; i++){
var url = await retorno.items[i].getDownloadURL();
conteudo.add(
ItemLab(
tipo: 'FILE',
elemento: retorno.items[i],
imageUrl: url,
),
);
if(limit != null){
if(conteudo.length > limit){
hasMore = true;
return Stream.value(conteudo);
}else{
hasMore = false;
print("less than 9");
}
}
}
try {
if(subPathSlashless.isNotEmpty){
print(subPathSlashless);
List items;
await databaseReference
.collection("lab_${pathSlashless}_url")
.snapshots().forEach((element) {
element.docs.forEach((f) {
if(f.data()['videos'] != null){
items == null ? items = f.data()['videos'] :
items.addAll(f.data()['videos']);
};
print("ITEMS :::: >>> ${items}");
});
});
for(int i = 0; i < items.length; i ++){
//print(items[i]);
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: items[i],
),
);
}
}else{
await databaseReference
.collection("lab_${pathSlashless}_url")
.snapshots().forEach((element) {
element.docs.forEach((f) {
if(f.data().isNotEmpty){
print(f.data());
if(f.data().keys.contains("videos")){
conteudo.add(
ItemLab(
tipo: 'PASTA',
pastaVideo: findFolderName(f.reference.path)
),
);
}else{
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: f.data(),
),
);
}
}
});
});
}
}catch(e){
print(e);
}
pathSlashless = null;
subPathSlashless = null;
conteudo = checkDuplicateFolder(conteudo, submenu);
return Stream.value(conteudo);
}
这是我的清单:
return StreamBuilder(
stream: ctrl.loadList(submenu),
builder: (ctx, snapshot) {
但是,如果我运行这段代码,它会抛出这个错误:
“未来”类型不是“流”类型的子类型
我该如何处理才能使用流而不是 Future 动态更新列表
解决方案
您不能等待 .snapshots(),因为它返回流,您可以将其更改为获取。还可以了解更多关于flutter firebase实时和正常用例的信息,查看flutter fire docs
loadList(String submenu, [int limit]) async {
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
List<ItemLab> conteudo = [];
if(subPathSlashless.isEmpty || subPathSlashless == null){
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
});
}
for(int i = 0; i < retorno.items.length ; i++){
var url = await retorno.items[i].getDownloadURL();
conteudo.add(
ItemLab(
tipo: 'FILE',
elemento: retorno.items[i],
imageUrl: url,
),
);
if(limit != null){
if(conteudo.length > limit){
hasMore = true;
return Stream.value(conteudo);
}else{
hasMore = false;
print("less than 9");
}
}
}
try {
if(subPathSlashless.isNotEmpty){
print(subPathSlashless);
List items;
(await databaseReference
.collection("lab_${pathSlashless}_url")
.get()).docs.forEach((f) {
if(f.data()['videos'] != null){
items == null ? items = f.data()['videos'] :
items.addAll(f.data()['videos']);
};
print("ITEMS :::: >>> ${items}");
});
for(int i = 0; i < items.length; i ++){
//print(items[i]);
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: items[i],
),
);
}
}else{
(await databaseReference
.collection("lab_${pathSlashless}_url")
.get()).docs.forEach((f) {
if(f.data().isNotEmpty){
print(f.data());
if(f.data().keys.contains("videos")){
conteudo.add(
ItemLab(
tipo: 'PASTA',
pastaVideo: findFolderName(f.reference.path)
),
);
}else{
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: f.data(),
),
);
}
}
});
}
}catch(e){
print(e);
}
pathSlashless = null;
subPathSlashless = null;
conteudo = checkDuplicateFolder(conteudo, submenu);
return conteudo;
}
和名单
return FutureBuilder(
future: ctrl.loadList(submenu),
builder: (ctx, snapshot) {
推荐阅读
- angular - Angular 8 Module 明智地加载外部 CSS/SCSS
- spring - 我可以听尤里卡的任何事件吗
- python - 如何比较python中还包含下划线等其他ascii符号的字符串?
- javascript - 删除重复数组并合并值
- python - 为什么if语句中的for循环没有执行?
- java - 具有多个键的 Spring Boot Cache 实现
- reactjs - Material-UI - 设置 ListItemSecondaryAction 的选定颜色
- python - 用python进行主成分分析
- google-analytics-api - 完整的目标清单
- html - 有序列表格式 1.1 1.2 1.2.1 但列表使用 start 属性