【问题标题】:The callback triggered after build method of child widget to set the state of parent widget doesn't trigger the build method of its parent子widget的build方法后触发的设置父widget状态的回调不会触发其父widget的build方法
【发布时间】:2020-05-14 11:13:54
【问题描述】:

我有一个称为(为此 sn-p)MainLayout 的父小部件和一个称为 ChildWidget 的子小部件。在执行其构建方法后,我想在子小部件的 AppBar 的操作中添加一个 IconButton。父级 AppBar 中显示的操作存储在其状态中。

我使用的方法有问题:在子窗口小部件的构建方法之后触发的设置其父窗口小部件状态的回调不会触发其父窗口的构建方法,但状态(父母的)改变了。因此,搜索图标没有挂载在 MainLayout 的 AppBar 的操作中。

为什么要这样做以及如何解决?

下面的代码是我的子小部件和父小部件的示例:

child_widget.dart

class ChildWidget extends StatelessWidget {
  // Add a search button in the AppBar of MainLayout widget.
  void _updateAppBar(BuildContext context) async {
    InheritedMainLayout.of(context).appBar.updateActions(<Widget>[
            IconButton(
              icon: Icon(Icons.search),
              onPressed: () => showSearch(
                context: context,
                delegate: SearchPageDelegate(),
              ),
            ),
          ]);
  }

  @override
  Widget build(BuildContext context) {
    _updateAppBar(context);
    return Container(
      width: 100,
      height: 100,
      color: Colors.blue,
    );
  }
}

parent_widget.dart

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => new _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  // This is the method that is passed as a parameter to the ChildWidget to update the actions of the AppBar.
  void _updateAppBarActions(List<Widget> actions) =>
    setState(() => _appBarActions = actions);

  @override
  Widget build(BuildContext context) {
    return InheritedMainLayout( // The inherited widget used to use the _updateAppBarActions method in the child widget
      appBar: new AppBarConfig(
        actions: _appBarActions,
      ),
      child: Scaffold(
        appBar: AppBar(
          title: Text("Title of the App"),
          actions: _appBarActions, // Actions showed in the AppBar are from the state, _appBarActions
        ),
        body: Padding(
          padding: EdgeInsets.all(20.0),
          child: _currentChild, // Here is loaded the builded widget called ChildWidget.
        ),
        drawer: AppDrawer(
          items: _drawerItems,
          onTap: _onChangePage,
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    您可能会看到此问题,因为您无法在构建过程中调用 setState。您可以使用 addPostFrameCallback 方法在构建过程之后调用您的回调。例如,请参阅此问题的答案Calling setState() during build without user interaction

    【讨论】:

    • 我以前看过那个帖子。问题是我不知道在哪里调用 addPostFrameCallback 以指示在那里工作(没有创建无限循环,避免在子小部件的构建方法中使用该方法)。对于我的情况(为了避免无限循环),我认为有必要使用我称为 _isMounted 的属性来了解操作是否已在 AppBar 中呈现。具体来说,我添加了一个 if 语句来评估 _isMounted 是否为 false 以更新 AppBar 的操作,而在相反的情况下什么也不做。
    • 如果你可以在构建中调用 setState,你仍然会有一个无限循环,因为将状态队列设置为另一个构建/渲染。使用您提到的布尔标志是一个很好的解决方案。
    猜你喜欢
    • 2019-02-04
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    • 2021-03-14
    • 1970-01-01
    • 2021-02-11
    相关资源
    最近更新 更多