dart - Nested Future 中的导航

标签 dart flutter

编辑:在这个新问题主题中完全按照我的意愿解决了问题:

Conditional Navigation inside Widget Tree

老问题:

这是我的启动屏幕,我想创建条件导航,但据我所知,FutureBuilder 没有导航逻辑。

这是我的启动屏幕构建方法:

@override
Widget build(BuildContext context) {
  return Material(
    child: ScopedModelDescendant<MainModel>(
      builder: (BuildContext context, Widget child, MainModel model) {
        return FutureBuilder(
          future: model.bootUp(),
          builder: (context, bootSnapshot) {
            print('====${bootSnapshot.data} is SNAPSHOT DATA====');
            return !bootSnapshot.hasData
                ? _buildSplash(context)
                : bootSnapshot.data
                    ? FutureBuilder(
                        future: model.fetchAll(model.tempUser),
                        builder: (context, dataSnapshot) {
                          return !dataSnapshot.hasData
                              ? _buildSplash(context)
                              : Navigator.of(context).pushReplacement(
                                  MaterialPageRoute(
                                      builder: (context) => HomePage()),
                                );
                        })
                    : Navigator.of(context).pushReplacement(
                        MaterialPageRoute(
                          builder: (context) => FirstScreen(),
                        ),
                      );
          },
        );
      },
    ),
  );
}

正如您在代码中看到的,首先我使用异步方法检查用户之前是否登录过,然后如果他之前登录过,那么我正在获取与他相关的数据,一旦获取完成我想导航到用户主页。

错误日志:

I/flutter (24348): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (24348): The following assertion was thrown building FutureBuilder<String>(dirty, state:
I/flutter (24348): _FutureBuilderState<String>#e0594):
I/flutter (24348): setState() or markNeedsBuild() called during build.
I/flutter (24348): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter (24348): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter (24348): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter (24348): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter (24348): Otherwise, the framework might not visit this widget during this build phase.
I/flutter (24348): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (24348):   Overlay-[LabeledGlobalKey<OverlayState>#c7eb6](state: OverlayState#953bd(entries:
I/flutter (24348):   [OverlayEntry#b9486(opaque: false; maintainState: false), OverlayEntry#af059(opaque: false;
I/flutter (24348):   maintainState: true), OverlayEntry#81d00(opaque: false; maintainState: false),
I/flutter (24348):   OverlayEntry#be7c4(opaque: false; maintainState: true)]))
I/flutter (24348): The widget which was currently being built when the offending call was made was:
I/flutter (24348):   FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#e0594)
I/flutter (24348):
I/flutter (24348): When the exception was thrown, this was the stack:
I/flutter (24348): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3485:11)
I/flutter (24348): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3511:6)
I/flutter (24348): #2      State.setState (package:flutter/src/widgets/framework.dart:1146:14)
I/flutter (24348): #3      OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:301:5)
I/flutter (24348): #4      OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)
I/flutter (24348): #5      TransitionRoute.install (package:flutter/src/widgets/routes.dart:185:11)
I/flutter (24348): #6      ModalRoute.install (package:flutter/src/widgets/routes.dart:861:11)
I/flutter (24348): #7      NavigatorState.pushReplacement (package:flutter/src/widgets/navigator.dart:1618:14)
I/flutter (24348): #8      BootScreen.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:mostadam/pages/boot_screen.dart:49:49)
I/flutter (24348): #9      _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
I/flutter (24348): #10     StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter (24348): #11     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter (24348): #12     Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter (24348): #13     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter (24348): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
I/flutter (24348): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter (24348): #16     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter (24348): #17     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter (24348): #18     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter (24348): #19     _invoke (dart:ui/hooks.dart:154:13)
I/flutter (24348): #20     _drawFrame (dart:ui/hooks.dart:143:3)

最佳答案

编辑:下面的答案非常古老。真正的解决方案是使用 WidgetsBinding。在 snapshot.hasData 条件下,放置此方法:

    WidgetsBinding.instance!.addPostFrameCallback((_) {
      Navigator.of(context)
          .pushReplacement(MaterialPageRoute(builder: (context) {
        if (~snapshot condition~) {
          return HomePage();
        }
        return FirstPage();
      }));
    });

addPostFrameCallback 是在 build 方法执行完成后立即执行一次的方法。

Anmol 已经回答了评论中的问题。

解决方案很简单,只需返回您要导航的页面即可。但对于一些罕见的特定情况,IMO 还不够。我希望我们在未来的更新中有更好的选择。

解决方法:

代替

Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => 首页();

简单地说:

return HomePage();

同样适用于:

return FirstScreen();

关于dart - Nested Future 中的导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54691767/

相关文章:

dart - flutter 异步函数 : _Future<String> returned instead of string value when subfunction is done

dart - 使用通用 bloc 提供程序时 bloc 不会被初始化

flutter - 过滤ListView、延迟搜索、查找、Debounce flutter 和 dart

flutter - 'keytool'在flutter中未被识别为内部或外部命令,可操作程序或批处理文件

flutter - 在Dart中将整数转换为 boolean 列表

dart - 为什么 `== null` 优于 `is Null` ?

flutter - 在 Flutter 项目中导入和导出文件

flutter - Dart 的广播流中的 forEach 会泄漏吗?

flutter - 如何将 flutter 移动应用程序迁移到 flutter web

flutter - 将ListView元素的CheckBox的位置传递给Flutter中的onChanged回调