InheritedWidget更新导致问题

InheritedWidget update cause problems

每当设置新位置时,我都会使用应用程序顶部的继承小部件来更新我的应用程序。这会在我的应用程序中的每个可能位置刷新我的位置坐标。

不过我也有一个文本框。几秒钟后当我点击文本字段时 键盘将被继承的小部件的更新隐藏。 有没有办法防止颤振隐藏键盘或重新初始化状态,以便继承的小部件的更新与我的搜索字段一起工作? 也有可能,当我输入一些文本时,这会触发继承的小部件进行新的更新,但搜索栏和键盘应该保持打开状态。

 new TextField(
          controller: _controller,
          autocorrect: false,
          autofocus: true
          ...
)

如果不查看所有代码,就很难知道发生了什么。

不过我最好的猜测是您正在使用 TextField 上方某处的上下文来注册继承的小部件的更新。

我建议您做的是从您的 TextField 向上移动小部件树,并确保您没有在其上方任何位置的上下文中使用继承的小部件。可能值得在构建方法的开头放置一些调试语句,以确定从何处触发构建(继承的小部件 不应该 在它下面立即触发重建,如果你我正在正确使用它,但奇怪的事情发生了。

这包括如果你有这样的事情:

MyWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    Location location = MyInheritedWidget.of(context).location;
    return new Row(
      children: [
        new LocationDisplayer(location),
        new TextField( ..... ),
      ],
    );
  }    
}

我之所以这样说,是因为我对继承的小部件如何工作的理解;当它发生变化时,将重建其上下文用于获取继承的小部件的小部件。

这意味着即使您的文本字段在技术上没有更改任何属性,它实际上可能是一个新的文本字段,具体取决于构建的方式(有一点颤振魔法我不完全理解他们如何决定什么时候制作新东西 vs re-build 东西)因此它没有请求焦点。

不必编写一堆新的小部件来封装任何使用 MyInheritedWidget 的东西,我相信你可以使用这样的东西:

MyWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    return new Row(
      children: [
        new Builder(
          builder: (context) {
            Location location = MyInheritedWidget.of(context).location;
            return new LocationDisplayer(location);
          },
        ),
        new TextField( ..... ),
      ],
    );
  }    
}

如果你 100% 确定你不会在任何地方这样做,那么你可以采用 non-flutter 做事的方式......你的位置 class 可以公开订阅和退订方法。您实际使用位置的所有小部件都调用订阅(也应该是有状态小部件),在它们的 initState() 中使用回调并在它们的 dispose() 中取消订阅。位置 class 将简单地调用每个回调而不是像您现在所做的那样更改状态,并且在每个回调中您应该为实际显示位置的小部件调用 setState