在 Flutter 中完成“构建”功能时是不是有任何回调告诉我?

Posted

技术标签:

【中文标题】在 Flutter 中完成“构建”功能时是不是有任何回调告诉我?【英文标题】:Is there any callback to tell me when "build" function is done in Flutter?在 Flutter 中完成“构建”功能时是否有任何回调告诉我? 【发布时间】:2018-12-15 10:04:53 【问题描述】:

我的屏幕上有一个 listView。我已将控制器连接到它。我可以调用我的端点,接收响应,解析它并插入行。 ListView 应该自动滚动。确实如此,但不是以完美的方式。我总是落后。这是我的代码:

@override
  Widget build(BuildContext context) 
    // Scroll to the most recent item
    if (equationList.length > 0) 
      _toEnd();
    

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: EquList(equationList, _scrollController),
      floatingActionButton: new FloatingActionButton(
        onPressed: onFabClick,
        tooltip: 'Fetch Post',
        child: new Icon(isLoading ? Icons.pause : Icons.play_arrow),
      ),
    );
  

  void _toEnd() 
    _scrollController.animateTo(
      _scrollController.position.maxScrollExtent,
      duration: const Duration(milliseconds: 250),
      curve: Curves.ease,
    );
  

问题是,我在最后一项插入列表之前调用了_toEnd() 函数。所以,我正在寻找一个回调(如果有的话)告诉我build() 已经完成。然后我调用我的_toEnd() 函数。

在这种情况下,最佳做法是什么?

【问题讨论】:

请注意,我们更喜欢这里的技术写作风格。我们轻轻地劝阻问候,希望你能帮助,谢谢,提前感谢,感谢信,问候,亲切的问候,签名,请你能帮助,聊天材料和缩写 txtspk,恳求,你多久了被卡住、投票建议、元评论等。只需解释您的问题,并展示您尝试过的内容、预期的内容以及实际发生的情况。 更好的方法是在ListView 中设置reverse: true 或滚动视图(如果您使用一个并以相反的顺序传递内容)。 @GünterZöchbauer,我正在这样做。但问题是,我仍然需要一个回调来告诉我构建完成。 你需要它做什么? build() 是同步的,所以如果你在 build() 中执行异步操作,它将在 build() 完成后执行。 谢谢@GünterZöchbauer,您可以举个例子回答您的建议吗?我是 Flutter 的新手,恐怕我没有让你好起来。谢谢。 【参考方案1】:

一般解决方案

只是为了澄清一下,我没想到这个问题会引起如此多的关注。因此,我只回答了这个非常具体的案例。 正如explained in another answer WidgetsBinding 提供了一种添加一次性 后帧回调的方法。

WidgetsBinding.instance.addPostFrameCallback((_) 
  // executes after build
)

由于此回调将only be called a single time,因此您需要在每次构建时添加它:

@override
Widget build(BuildContext context) 
  WidgetsBinding.instance.addPostFrameCallback((_) => afterBuild);
  return Container(); // widget tree


void afterBuild() 
  // executes after build is done

特定(异步)

详述Günter's评论:

@override
Widget build(BuildContext context) 
  executeAfterBuild();
  return Container();


Future<void> executeAfterBuild() async 
  // this code will get executed after the build method
  // because of the way async functions are scheduled

有一个很好的例子illustrating that effect here。 关于Dart 中调度的详细信息can be found here。

【讨论】:

我不知道同步功能完成后会运行异步。它像魅力一样工作。感谢您的示例代码。 @creativecreatorormaybenot 我不认为仅仅通过将函数标记为异步(使用async 关键字),其中的代码将被安排在事件队列中。您应该使用Future(() ) 或它的其他构造函数形式。 异步函数内部的代码不能是任意随机代码。我们必须确保我们返回一个 Future 对象,然后编写我们想要实际执行的代码。例如: Future executeAfterBuild() async await Future.delayed(Duration(milliseconds:10)); )// 要执行的代码 .当这个 async 函数被调用时,我们会得到一个未完成状态的 Future 对象,因为我们调用了这个 async 函数而不做 await。【参考方案2】:

@creativecreatorormaybenot 的异步方式足以回答大多数情况下的问题。

但如果你想setState() 或在构建小部件后立即更改树中的小部件,则不能使用异步方式。因为回调将在小部件树的构建过程中触发。它会抛出一个异常:

Dart Error: Unhandled exception:
E/flutter (25259): setState() or markNeedsBuild() called during build.

对于这种情况,你可以注册一个post frame回调来修改widget:

@override
Widget build(BuildContext context) 
  WidgetsBinding.instance
    .addPostFrameCallback((_) => executeAfterWholeBuildProcess(context));

【讨论】:

接受的答案错过了作为参数的“上下文”。因为它对我来说不能正常工作

以上是关于在 Flutter 中完成“构建”功能时是不是有任何回调告诉我?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter,是不是可以在没有小部件构建方法的情况下在功能中使用 Firestore Stream Builder?

Flutter 构建 iOS 错误:在 iOS 设备中构建 Flutter 应用程序时遇到错误

Flutter 中如何从字符串中获取语言代码扑

ProcessException:进程超时:当xode构建完成Flutter应用程序时

如何在 Flutter 中基于 Future 结果构建 Stream?

Flutter ListView 在构建时滚动到底部