【问题标题】:type 'Future<dynamic>' is not a subtype of type 'Stream<dynamic>' getting data from Firebase'Future<dynamic>' 类型不是从 Firebase 获取数据的 'Stream<dynamic>' 类型的子类型
【发布时间】:2021-02-19 01:38:31
【问题描述】:

我正在从 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 动态更新列表

【问题讨论】:

  • 这是一个需要知道你实际上想要做什么才能知道如何回答你的问题的情况。标记为async 的方法必须返回Future,而您正试图将其输入需要StreamStreamBuilder。但是为了解决这个问题,你需要走哪个方向取决于你想要做什么。如果您需要返回Stream,请使用async*,但如果您实际上想返回Future,请改用FutureBuilder

标签: flutter dart stream-builder


【解决方案1】:

你不能等待.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) {

【讨论】:

  • 但我想返回一个 Stream 以便能够动态修改列表...您能帮忙吗?
  • 请检查cmets
猜你喜欢
  • 2021-08-18
  • 1970-01-01
  • 2021-08-12
  • 2021-09-18
  • 2021-08-13
  • 2020-09-24
  • 2020-09-11
  • 2020-10-13
  • 2019-12-31
相关资源
最近更新 更多