【问题标题】:Compute method not calling in FutureBuilder计算方法未在 FutureBuilder 中调用
【发布时间】:2021-10-09 20:14:27
【问题描述】:

我注意到一旦选择了一个大文件,我的应用就会冻结。所以我想出了一个想法,让字节在隔离线程中生成。完成生成后,让它显示在Image 小部件中。

第一个选择的文件将被添加到 urlImageSink 中。

@override
  Future<String>userImage(File images) async {
    if (images.path.contains(".pdf")) {
      urlListImages.add(images.path);
      _bloc.urlImageSink.add(urlListImages);
    } 
  }

接下来它将运行StreamBuilder,在FutureBuilder中调用loadPdfFirstPage

 Widget _showAttachFile() {
    return Padding(
      padding: EdgeInsets.all(10),
      child: StreamBuilder<List<dynamic>>(
          stream: _bloc.urlImageStream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return GridView.builder(
                  shrinkWrap: true,
                  physics: NeverScrollableScrollPhysics(),
                  gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    mainAxisSpacing: 5.0,
                    crossAxisSpacing: 5.0,
                  ),
                  itemCount: snapshot.data.length + 1,
                  itemBuilder: (BuildContext context, int index) => new Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: Container(
                          padding: EdgeInsets.zero,
                          height: 150,
                          width: 150,
                          child: FutureBuilder<Uint8List>(
                            future:
                                loadPdfFirstPage(File(snapshot.data[index])),
                            builder: (context, snapshot) {
                              switch (snapshot.connectionState) {
                                case ConnectionState.done:
                                  if (snapshot.hasData) {
                                    return Image(
                                        image: MemoryImage(snapshot.data));
                                     );
                                  } else {
                                    return Text("Null");
                                  }
                                  break;

                                case ConnectionState.waiting:
                                  return CircularProgressIndicator();
                                  break;

                                default:
                                  return Text("Error");
                              }
                            },
                          ),
                        ),
                      ));
            } else {
              return Text("No Data");
            }
          }),
    );
  }

在 loadPdfFirstPage 方法中,我运行了 compute 方法来生成字节。

Future<Uint8List> loadPdfFirstPage(File pdfFile) =>
      compute(generateBytes, pdfFile);

  Future<Uint8List> generateBytes(File pdfFile) async {
    final document = await PdfDocument.openFile(pdfFile.path);
    final page = await document.getPage(1);
    final pageImage = await page.render(width: page.width, height: page.height);
    await page.close();

    return pageImage.bytes;
  }

每次选择文件时,我都会立即从FutureBuildersnapshot.data 获取输出NullloadPdfFirstPage 好像没有打电话。

我在这里做错了什么?

【问题讨论】:

  • generateBytes 是在哪里定义的?
  • @LayneBernardo 在计算函数中。
  • Isolates communicate by passing messages back and forth. These messages can be primitive values, such as null, num, bool, double, or String, or simple objects such as the List&lt;Photo&gt; in this example. 所以我觉得File 不简单
  • @Nagual 但如果我想选择一个大文件怎么办?
  • 我没有检查,但尝试将其 base64 编码为字符串并改为传递 Uint8List,与文件相同 - 尝试不传递文件,而仅传递路径(字符串)

标签: flutter dart stream-builder flutter-futurebuilder isolation


【解决方案1】:

您当前的问题似乎是,您还没有创建一个变量来保存您的未来一次。从 build 方法创建的 FutureBuilder 将一遍又一遍地调用该方法。每次调用 build 方法时都会调用它。

你需要一个创建你想要等待的未来的地方,并且它必须在构建方法中的其他地方。

也就是说,如果我正确解释了名为 _bloc 的变量,那么您使用的是 BLoC 模式吗?你应该有事件和状态。您不应该需要 FutureBuilder,拥有一个新文件应该是一个事件,等待它加载应该是一个状态,加载完成应该是它自己的状态。然后你的 BLoC 类中有一个逻辑,它有一个流程,你有一个 UI,不需要知道什么触发了什么,只显示状态。

【讨论】:

  • 如果不需要FutureBuilder,我应该把loadPdfFirstPage放在哪里?
  • 在 BLoC 内部,因为它是业务逻辑。但总的来说很难说,因为那是你的应用程序的架构,我对此一无所知。我可以肯定地说 loadPdfFirstPage 的调用属于你的状态管理代码,而不是你的构建方法。
  • 你能分享一些代码示例来解决这个问题吗?谢谢。
  • 我无法共享代码示例。这不是两行代码就能解决的问题。您必须在程序中找到运行逻辑的位置。 那里您必须创建一个“Future”类型的变量,并且那个变量必须在构建方法中转到您的FutureBuilder。您不能在构建方法中进行状态管理。
猜你喜欢
  • 2021-11-30
  • 1970-01-01
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多