打开键盘会导致状态小部件重新初始化

时间:2019-03-19 05:26:47

标签: flutter

我在稳定分支中使用Flutter 1.2.1。为了说明我的问题,假设我有A页和B页。A使用Navigator.push导航到B,而B使用Navigator.pop导航回A。两者都是有状态的小部件。

当我从A导航到B,然后弹出回到A时,一切都很好,并且A保持其状态。但是,如果我从A导航到B,请在B中点击一个文本字段以打开键盘,然后关闭键盘并弹出回到A,A的整个状态都会刷新,并再次调用A的initState()方法。我通过使用打印语句对此进行了验证。

仅当我在弹回A之前打开键盘时才会发生这种情况。如果我导航到B,然后立即导航回A而没有任何交互,那么A会保持其状态并且不会重新初始化。

据我了解,build方法一直被调用,但是initState()不应这样调用。有人知道发生了什么吗?

4 个答案:

答案 0 :(得分:0)

您是否在“ A”小部件中使用了AutomaticKeepAliveClientMixin? 如果不这样做,请参见此https://stackoverflow.com/a/51738269/3542938 如果您已经使用过它,请给我们提供一个代码,我们可以将其直接测试到“ main.dart”中以帮助您

答案 1 :(得分:0)

经过反复尝试,我确定了问题所在。我忘记了在select DriverVersion,Description from Win32_PnPSignedDriver WHERE Description in ('Dell Touchpad', 'WiFi') 小部件中为FutureBuilder路由设置了/。我正在传递一个函数调用,该函数调用将Future返回到MaterialApp构造函数的future参数,而不是指向Future的变量。

因此,每当路线更新时,都会创建一个全新的未来。在FutureBuilder构造函数之外进行函数调用,并将结果future存储在变量中,然后将其传递给MaterialApp就可以了。

这似乎与打开键盘时出现的怪异行为无关,但这绝对是原因。我的意思见下文。

有错误的代码:

FutureBuilder

固定代码:

return MaterialApp(
  title: appTitle,
  theme: ThemeData(
    primarySwatch: Colors.teal,
    accentColor: Colors.tealAccent,
    buttonColor: Colors.lightBlue,
  ),
  routes: {
    '/': (context) => FutureBuilder<void>(
          future: futureFun(), //Bug! I'm passing a function that returns a future when called. So a new future is returned each time
          builder: (context, snapshot) {
          ...
          }
      ...
  }
  ...
}

答案 2 :(得分:0)

是的,发生在我身上,也许最好将FutureBuilder包装成一个PageWidget,并使其单例化

    return MaterialApp(
      title: appTitle,
      theme: ThemeData(
        primarySwatch: Colors.teal,
        accentColor: Colors.tealAccent,
        buttonColor: Colors.lightBlue,
      ),
      routes: {
        '/': (context) => PageWidget() // wrap it by PageWidget
          ...
      }
      ...
    }


    class PageWidget extends StatelessWidget {
      static final _instance = PageWidget._internal(); // hold instance

      PageWidget._internal(); // internal consturctor

      factory PageWidget() {
        return  _instance;    // make it singleton
      }

      @override
      Widget build(BuildContext context) {
        return FutureBuilder<void>( ... );
      }
    }

答案 3 :(得分:0)

我有一个解决方案,我正在超类的构造函数中初始化变量。我将其删除并开始工作!