首页 > 解决方案 > Navigator.push 将在 Navigator.push 之后关注目标页面上的文本字段时再次调用

问题描述

出现以下现象。

  1. 从 过渡FirstPageNextPageby Navigation.push
  2. 选择一个TextFieldNextPage
  3. 1 再次被调用。
  4. 用键盘搞定。
  5. 1 再次被调用。

下面是源码。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("sample"),
      ),
      body: RaisedButton(
        onPressed: () {
          Navigator.of(context).push(
            MaterialPageRoute(builder: (context) {
              print("Before call NextPage()");
              return NextPage();
            }),
          );
        },
        child: Text("next page"),
      ),
    );
  }
}

class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("next page"),
      ),
      body: TextField(),
    );
  }
}

下面是在点击 TextField 和 DONE 键盘时打印日志的动画 gif。

在此处输入图像描述

为什么会这样?(错误?)
我该如何解决?

标签: flutter

解决方案


如您所见,即使该日志被多次调用,您也只会看到第一个的转换,或者换句话说,您正在获得所需的效果。发生这种情况是有原因的。让我们分解一下:

使用Flutter,builders可以多次调用,多种原因,并且应该是幂等的(不影响逻辑业务);

话虽如此,当您导航到第二个屏幕时,您正在构建一个Stateless WidgetTextFormField `的子级,它应该是不可变的。这意味着它的最终值(如果需要)应该在构造函数中传递,并且每次状态更改(例如字段的默认文本)都将需要更改,从而通过触发构建器来重建视图;

因此,例如,如果您改用Stateful Widget,则可能不会调用您的构建器,而只会调用buildState的方法。

您可以在此处的类似已关闭问题中找到有关此问题的讨论


推荐阅读