Flutter的根widget是否始终应该是StatelessWidget?

3
阅读Flutter文档时,我有一个问题:Flutter的根组件是否总是StatelessWidget?
 class MyApp extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
       title: 'Flutter Code Sample for Navigator',
       // MaterialApp contains our top-level Navigator
       initialRoute: '/',
       routes: {
         '/': (BuildContext context) => HomePage(),
         '/signup': (BuildContext context) => SignUpPage(),
       },
     );
   }
 }
  1. 因为我认为有时需要调用init函数,但可能不希望将其代码编写在HomePage中。例如:检查token是否过期,决定前往HomePage还是LoginPage。
  2. 那么最好的选择:我应该将根Widget更改为StatefulWidget,并将上述逻辑包含在其initState函数中吗?

1
简短的回答是不。 - Salma
不,它不必是无状态的。除非您在根Widget的生命周期事件期间改变状态。 - MJ Montes
@MJ Montes 如果只需要执行某些任务,而不改变任何状态本身,该怎么办? - JerryZhou
你可以在无状态小部件中执行通常的任务。 - MJ Montes
3个回答

3

将根小部件设置为一个StatefulWidget在监听AppLifecycleState时非常有用,
例如,在恢复WebSocket连接等方面进行恢复工作。

代码片段

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {

  AppLifecycleState _lastLifecycleState;


  @override
  void initState() {
    super.initState();
    initPlatformState();
    WidgetsBinding.instance.addObserver(this);

  }

  initPlatformState() async {
    Screen.keepOn(true);   
  }

  Future<void> resumeCallBack() {
    if (sl<WebSocketService>().webSocketState == 'lost') {
      sl<WebSocketService>().initWebSocket();
    }

    if (mounted) {
      setState(() {});
    }
    print("resumeCallBack");
  }

  Future<void> suspendingCallBack() {
    if (mounted) {
      setState(() {});
    }
    print("suspendingCallBack");
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    print("AppLifecycleState Current state = $state");
    setState(() {
      _lastLifecycleState = state;
    });

    switch (state) {
      case AppLifecycleState.inactive:
      case AppLifecycleState.paused:
      case AppLifecycleState.detached:
      /*case AppLifecycleState.suspending:
        await suspendingCallBack();
        break;*/
      case AppLifecycleState.resumed:
        await resumeCallBack();
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Template',
      debugShowCheckedModeBanner: false,
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => LoginPage(),

2

是的,您可以使用StatefulWidget作为根父元素。但是,只有在有意义的情况下才应使用它。

例如,如果您正在初始化和观察某些动画、Firebase消息传递、服务、应用程序生命周期状态等,这可能需要一些时间。

否则,无状态小部件更好用。


1
它可以是StatefulWidgetStatelessWidget。但将StatefulWidget放在根位置会影响应用性能,因为在StatefulWidget中的简单状态更改将导致整个小部件树重建并降低应用程序性能。
始终尝试将StatefulWidgetInheritedWidget深度嵌套在小部件树中。
对于您的情况,更好的解决方案是使用ProvidersInheritedWidgets并监听令牌更改,而不是将根小部件更改为有状态的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接