【问题标题】:TextField click rebuilds/reloads widget after routed路由后,TextField 单击重建/重新加载小部件
【发布时间】:2018-11-22 08:27:31
【问题描述】:

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

但是当路由从另一个页面发生到这个页面并且当点击文本字段时,就会发生重建。

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

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,单击按钮 Go to screen2 将加载带有文本字段的屏幕 2。单击此字段将显示键盘并单击键盘上的完成并再次关注文本字段将重建屏幕。当键盘出现和消失时,这种情况不断发生。

但是如果将 Screen2 设置为登录页面,则单击文本字段并执行上述相同过程将不会重新加载小部件。小部件构建只发生一次。似乎问题是从 Screen 1 导航 Screen2 时

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

【问题讨论】:

    标签: android dart flutter flutter-layout


    【解决方案1】:

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

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

    这些不应该在build 方法中完成。更多细节在这里:How to deal with unwanted widget build?


    关于“什么触发构建”,有几种常见的情况:

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

    【讨论】:

    • 这种情况有什么副作用?
    • 您基本上希望在initState 方法中初始化任何交互式小部件,例如TextFormField,否则每次调用小部件的build 方法时都会重新构建它们。
    • 他的例子除了print之外没有任何副作用。但他的申请中可能有一些,否则不会引起问题
    • 他说他可以通过发布的示例代码重现问题。
    • 它实际上重建了整个应用程序,所有 initStates 都被再次调用,等等。根据我的理解,这不应该发生。我在 Flutter repo 中为它创建了一个 bug 票。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 2017-08-21
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      相关资源
      最近更新 更多