【问题标题】:Flutter - Keyboard Show and Hide Causes Build CallsFlutter - 键盘显示和隐藏导致构建调用
【发布时间】:2019-12-17 00:39:54
【问题描述】:

我最近一直在学习 Flutter,遇到了一些奇怪的问题,当我点击 TextField 时,将显示键盘,并且将为托管和所有祖先小部件调用 build

我读过当点击 TextField 时,build 方法将被调用,然后整个小部件将被重建,但我遇到的情况有点奇怪,因为在第一个打开的小部件上没有调用构建.

场景:

1 - 打开应用程序。

2 - 第一个小部件加载并打印在屏幕上:“First build called”,当我点击 TextField 时,键盘弹出,控制台上没有打印任何内容。

3 - 点击“Open Second”,第二个小部件加载并打印在屏幕上: “Second build called”,当我点击TextField时,键盘弹出并打印:“Second build called”(在步骤[1]中没有打印!) .

4 - 点击“Open First”,第一个小部件再次加载并打印在屏幕上:“First build called”,当我点击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 (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再选一次!

【问题讨论】:

  • 与此类似的问题,stackoverflow.com/questions/57409531/… 还将 'resizeToAvoidBottomInset: false' 添加到您的脚手架
  • @Mohammad:我也面临这个问题。你有什么解决办法吗?
  • @Jatin 请在下面查看我的答案。

标签: flutter dart


【解决方案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'),
  ),

【讨论】:

  • 这并没有解决问题,键盘无论如何都会在step3 中调用build 而没有在step2 中调用build,我不明白为什么!
  • 您的问题是关于由导航事件引起的重建,但我也向您指出了讨论由键盘事件引起的相同问题的帖子。根据帖子,可以使用类似的技术解决,谢谢。
【解决方案2】:

根据Mazin Ibrahim 的回答,我设法解决了键盘构建问题:

将所有导航器小部件定义为final,以防使用路由。

在使用路由的情况下,我设法将所有导航小部件定义为路由类中的final 字段。

不再重复创建同一个小部件,尤其是我的小部件都是Stateless

【讨论】:

    【解决方案3】:

    请记住,您应该始终编写您的 build 方法,就好像它们每秒被调用 60 次一样。所以它们应该是 (a) 快速和 (b) 幂等的。

    【讨论】:

      【解决方案4】:

      将 Scaffold 包装在 Consumer 小部件中或需要的地方。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多