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

Hes*_*sam 17 flutter

我的屏幕上有一个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,
    );
  }
Run Code Online (Sandbox Code Playgroud)

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

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

Roc*_*ice 32

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

但是,如果您想setState()在构建窗口小部件后立即执行某些操作来更改树中的窗口小部件,则无法使用异步方式.因为回调将在窗口小部件树的构建过程中触发.它会引发异常:

Dart Error: Unhandled exception:
E/flutter (25259): setState() or markNeedsBuild() called during build.
Run Code Online (Sandbox Code Playgroud)

对于这种情况,您可以注册一个后框架回调来修改窗口小部件:

@override
Widget build(BuildContext context) {
  WidgetsBinding.instance
    .addPostFrameCallback((_) => executeAfterWholeBuildProcess(context));
Run Code Online (Sandbox Code Playgroud)


cre*_*not 19

阐述君特的评论:

WidgetsBinding.addPostFrameCallback(() {
  // executes after build
})
Run Code Online (Sandbox Code Playgroud)

有一个很好的例子说明这种效果在这里.
有关Dart日程安排的 详细信息,请点击此处.

  • 我不知道同步功能完成后会运行异步。它的作用就像魅力一样。感谢您的示例代码。 (6认同)

Cop*_*oad 14

如果您不想使用WidgetsBinding

  • 使用FutureTimer

    @override
    Widget build(BuildContext context) {
      Timer(_runsAfterBuild); // <-- Just add this line 
      return Container();
    }
    
    Future<void> _runsAfterBuild() async {
      // This code runs after build ...
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 添加虚拟等待(修复@creativecreatureormaybenot问题)

    @override
    Widget build(BuildContext context) {
      _runsAfterBuild();
      return Container();
    }
    
    Future<void> _runsAfterBuild() async {
      await Future.delayed(Duration.zero); // <-- Add a 0 dummy waiting time
      // This code runs after build ...
    }
    
    Run Code Online (Sandbox Code Playgroud)