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
。
每当设置新位置时,我都会使用应用程序顶部的继承小部件来更新我的应用程序。这会在我的应用程序中的每个可能位置刷新我的位置坐标。
不过我也有一个文本框。几秒钟后当我点击文本字段时 键盘将被继承的小部件的更新隐藏。 有没有办法防止颤振隐藏键盘或重新初始化状态,以便继承的小部件的更新与我的搜索字段一起工作? 也有可能,当我输入一些文本时,这会触发继承的小部件进行新的更新,但搜索栏和键盘应该保持打开状态。
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
。