打开键盘会使有状态的小部件重新初始化 [英] Opening keyboard causes stateful widgets to be re-initialized
问题描述
我在稳定分支中使用Flutter 1.2.1.为了说明我的问题,想象一下我有A页和B页.A使用Navigator.push
导航到B,而B使用Navigator.pop
导航回到A.两者都是有状态的小部件.
I am using Flutter 1.2.1 in the Stable branch. To illustrate my problem imagine I have pages A and B. A navigates to B using Navigator.push
and B navigates back to A using Navigator.pop
. Both are stateful widgets.
当我从A导航到B,然后弹出回到A时,一切都很好,并且A保持其状态.但是,如果我从A导航到B,请在B中点击一个文本字段以打开键盘,然后关闭键盘并弹出回到A,A的整个状态都会刷新,并再次调用A的initState()
方法.我通过使用打印语句对此进行了验证.
When I navigate from A to B and then pop back to A everything is fine and A keeps its state. However, if I navigate from A to B, tap a textfield in B opening the keyboard, then close the keyboard and pop back to A, A's entire state is refreshed and the initState()
method for A is called again. I verified this by using print statements.
仅当我在弹回A之前打开键盘时才会发生这种情况.如果我导航到B,然后立即导航回A而没有任何交互,那么A会保持其状态并且不会重新初始化.
This only happens when I open the keyboard before popping back to A. If I navigate to B, then immediately navigate back to A without interacting with anything then A keeps its state and is not re-initialized.
据我了解,build方法一直被调用,但是initState()
不应像这样被调用.有人知道发生了什么吗?
From my understanding the build method is called all the time but initState()
should not get called like this. Does anyone know what is going on?
推荐答案
经过反复尝试,我确定了问题所在.我忘记了在MaterialApp
小部件中为/
路由设置了FutureBuilder
.我正在传递一个函数调用,该函数返回一个Future到FutureBuilder
构造函数的future
参数,而不是一个指向Future的变量.
After much trial and error I determined the problem. I forgot that I had setup a FutureBuilder
for the /
route in my MaterialApp
widget. I was passing a function call that returns a future to the future
parameter of the FutureBuilder
constructor rather than a variable pointing to a future.
因此,每当路线更新时,都会创建一个全新的未来.在MaterialApp
构造函数之外进行函数调用并将结果的future存储在变量中,然后将其传递给FutureBuilder
可以解决问题.
So every time the routes got updated a brand new future was being created. Doing the function call outside of the MaterialApp
constructor and storing the resulting future in a variable, then passing that to the FutureBuilder
did the trick.
这似乎与打开键盘时出现的怪异行为无关,但这绝对是原因.我的意思见下文.
It doesn't seem like this would be connected to the weird behavior I was getting when a keyboard opened, but it was definitely the cause. See below for what I mean.
有错误的代码:
return MaterialApp(
title: appTitle,
theme: ThemeData(
primarySwatch: Colors.teal,
accentColor: Colors.tealAccent,
buttonColor: Colors.lightBlue,
),
routes: {
'/': (context) => FutureBuilder<void>(
future: futureFun(), //Bug! I'm passing a function that returns a future when called. So a new future is returned each time
builder: (context, snapshot) {
...
}
...
}
...
}
固定代码:
final futureVar = futureFun(); //calling the function here instead and storing its future in a variable
return MaterialApp(
title: appTitle,
theme: ThemeData(
primarySwatch: Colors.teal,
accentColor: Colors.tealAccent,
buttonColor: Colors.lightBlue,
),
routes: {
'/': (context) => FutureBuilder<void>(
future: futureVar, //Fixed! Passing the reference to the future rather than the function call
builder: (context, snapshot) {
...
}
...
}
...
}
这篇关于打开键盘会使有状态的小部件重新初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!