我最近一直在学习Flutter,遇到一个奇怪的问题,当我单击TextField时,将显示键盘,并且将为托管的和所有祖先小部件调用build
。
我读到,当单击TextField时,将调用build
方法,然后将重建整个小部件,但是我遇到的情况有些奇怪,因为第一个未调用该构建打开的小部件。
场景:
1-打开应用。
2-第一个窗口小部件加载并打印在屏幕上:“第一个内部版本被调用” ,当我单击TextField时,键盘弹出,控制台上没有任何打印内容。
3-单击“打开第二个”,第二个小部件加载并打印在屏幕上: “第二个构建称为” ,当我单击TextField时,键盘弹出并打印:“第二个构建称为” (在步骤[1]中什么也没打印!)
4-单击“首先打开”,第一个窗口小部件再次加载并打印在屏幕上:“第一个内部版本已建立” ,当我单击TextField时,键盘弹出并打印: “第二个构建称为第一个构建” (在步骤[1]中,未打印任何内容的同一小部件!)。
代码:
void main() {
runApp(MaterialApp(home: First()));
}
class First extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('First build called');
return Scaffold(
appBar: AppBar(
title: Text("HI Ramadan"),
),
body: Column(
children: <Widget>[
TextField(),
RaisedButton(onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Second()));
}, child: Text('Open Second'),),
],
),
);
}
}
class Second extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Second build called');
return Scaffold(
body: Column(
children: <Widget>[
TextField(),
RaisedButton(onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => First()));
}, child: Text('Open First')),
],
),
);
}
}
Flutter医生:
[√] Flutter (Channel stable, v1.7.8+hotfix.4, on Microsoft Windows [Version 10.0.17134.885], locale en-US)
• Flutter version 1.7.8+hotfix.4 at C:\flutter
• Framework revision 20e59316b8 (3 weeks ago), 2019-07-18 20:04:33 -0700
• Engine revision fee001c93f
• Dart version 2.4.0
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
• Android SDK at C:\Users\ASUS\AppData\Local\Android\sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
• All Android licenses accepted.
[√] Android Studio (version 3.3)
• Android Studio at C:\Program Files\Android\Android Studio
• Flutter plugin version 34.0.1
• Dart plugin version 182.5215
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
[√] VS Code (version 1.36.1)
• VS Code at C:\Users\ASUS\AppData\Local\Programs\Microsoft VS Code
• Flutter extension version 3.2.0
[√] Connected device (1 available)
• FLA LX1 • 75U7N18410006702 • android-arm64 • Android 9 (API 28)
• No issues found!
问题:
1-为什么会发生这种情况(在不是树根的每个小部件上称为“构建”)?
2-有没有一种方法可以在键盘显示或隐藏时强制颤动不调用build
?因为我有表单,所以当我单击TextField
并键入内容时,然后单击DropDown
时,将显示DropDown
然后直接隐藏(因为调用了build
),我需要再点击DropDown
一次来选择!
答案 0 :(得分:1)
First
被重建,因为它在导航堆栈中的位置已更改。
对于您的键盘问题,此post解决了这一问题,您只需对代码做些微改动:
更改此内容:
RaisedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => Second()));
},
child: Text('Open Second'),
),
RaisedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => First()));
},
child: Text('Open First'),
),
收件人:
RaisedButton(
onPressed: () {
final page = Second();
Navigator.push(context,MaterialPageRoute(builder: (context) => page ));
},
child: Text('Open Second'),
),
RaisedButton(
onPressed: () {
final page = First();
Navigator.push(context,MaterialPageRoute(builder: (context) => page ));
},
child: Text('Open First'),
),
答案 1 :(得分:0)
基于Mazin Ibrahim的答案,我设法解决了键盘构建问题:
在使用路线的情况下,将所有导航器小部件定义为final
。
在使用路线的情况下,我设法将所有导航小部件定义为routes类中的final
字段。
这样就不止一次地重新创建相同的小部件,尤其是我的小部件都是Stateless
时。
答案 2 :(得分:0)
请记住,您应该始终编写build
方法,就好像它们每秒被调用60次一样。因此,它们应该(a)快速且(b)幂等。
答案 3 :(得分:0)
在“消费者”小部件中或需要的位置包装支架。