TextField单击可在路由后重建/重新加载小部件



我遇到一个问题,当使用文本字段时,整个屏幕小部件会重新加载。当应用程序加载此屏幕作为登录页时,不会发生这种情况。

但是,当从另一个页面到该页面进行路由时,并且当单击文本字段时,就会进行重建。

我甚至尝试了一个简单的应用程序,它正在被复制。尝试了很多方法,但都没有找到解决方案。

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Screen1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 1"), // screen title
),
body: new Center(
child: new Column(
children: <Widget>[
new RaisedButton(
onPressed: () {
button1(context);
},
child: new Text("Go to Screen 2"),
)
],
),
),
);
}
}
class Screen2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Widget rebuilds");
return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 2"),
),
body: new Center(
child: new Column(
children: <Widget>[
new Container(
height: 350.0,
child: TextFormField(
keyboardType: TextInputType.text,
style: TextStyle(fontSize: 16.0, color: Colors.black),
)),
],
),
),
);
}
}
void main() {
runApp(new MaterialApp(
home: new Screen1(),
routes: <String, WidgetBuilder>{
'/screen2': (BuildContext context) => new Screen2()
},
));
}
void button1(BuildContext context) {
print("Button 1");
Navigator.of(context).pushNamed('/screen2');
}

在这里,应用程序加载了屏幕1,点击按钮转到屏幕2将加载带有文本字段的屏幕2。单击此字段将打开键盘,单击done on键盘并再次关注文本字段将重建屏幕。这种情况在键盘出现和消失时都会发生。

但是,如果Screen2被设置为登录页,那么点击文本字段并执行上面提到的相同过程将不会重新加载小部件。小部件构建只发生一次。似乎问题出在从屏幕1 导航屏幕2时

runApp(new MaterialApp(
home: new Screen2(),
routes: <String, WidgetBuilder>{
'/screen2': (BuildContext context) => new Screen2()
},
));

这是正常行为,没有问题。事实上,它在build方法的规范范围内:它可以被称为任意数量的时间,你应该期望它是这样的

如果这导致了这样做的问题,那么很可能您的build函数是而非纯。这意味着它包含诸如http调用或类似的副作用。

这些不应在build方法中完成。这里的更多细节:如何处理不需要的小部件构建?


关于"什么触发构建",有一些常见的情况:

  • 路由弹出/推送,用于输入/输出动画
  • 屏幕大小调整,通常是由于键盘外观或方向改变
  • 父窗口小部件重新创建了其子窗口小部件
  • 小部件所依赖的InheritedWidget(Class.of(context)模式(更改

如果您正在使用MediaQuery,则键盘弹出会触发MediaQuery。所有依赖于MediaQuery的小部件都将被重建。有些包可以取代MediaQuery并处理维度,而不会导致不必要的重建,例如sizer包。

最新更新