首页 > 解决方案 > 是否可以根据用户角色从启动屏幕导航或推送到管理屏幕或用户屏幕?

问题描述

我正在使用 Flutter 和 firebase 创建一个 Web 应用程序。以下是依赖项:

  firebase_core: ^1.7.0
  firebase_auth: ^3.1.3
  cloud_firestore: ^2.5.3

以下是 web/index.html 上的脚本版本:

  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script>

我正在尝试使用电子邮件和密码方法登录后导航用户。用户应该导航到admin pageuser page依赖于user roleon cloud Firestore。登录后用户从登录页面将导航到splash screen应该决定用户导航到下一页的位置,具体取决于用户角色。它正在启动启动屏幕,但我无法做我想做的事情,页面不会被导航。请让我知道这是正确的方法,请给我一个解决方案。以下是我在启动画面上的测试代码:

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:webfire/admin_screen.dart';
import 'package:webfire/home_screen.dart';

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  String role = 'user';

  @override
  void initState() {
    super.initState();
    _checkRole();
  }

  final FirebaseAuth auth = FirebaseAuth.instance;
  
  void _checkRole() async {
    User? user = FirebaseAuth.instance.currentUser;
    //User user = auth.currentUser;
    final DocumentSnapshot snap = await FirebaseFirestore.instance
        .collection('users')
        .doc(user!.uid)
        .get();

    setState(() {
      role = snap['role'];
    });

    if (role == 'user') {
      navigateNext(const HomeScreen());
    } else if (role == 'admin') {
      navigateNext(const AdminScreen());
    }
  }

  void navigateNext(Widget route) {
    Timer(const Duration(milliseconds: 500), () {
      Navigator.pushReplacement(
          context, MaterialPageRoute(builder: (context) => route));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: const [
          Text('Welcome'),
        ],
      ),
    ));
  }
}

错误:打开 utils.dart 并显示:return util.promiseToFuture(thenable);

以下是根据第一个答案编辑的代码:

import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:webfire/admin_screen.dart';
import 'package:webfire/home_screen.dart';

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  String role = 'user';

  @override
  void initState() {
    super.initState();
    _checkRole();
  }

  final FirebaseAuth auth = FirebaseAuth.instance;

  void _checkRole() async {
    User? user = FirebaseAuth.instance.currentUser;
    //User user = auth.currentUser;
    final DocumentSnapshot snap = await FirebaseFirestore.instance
        .collection('users')
        .doc(user!.uid)
        .get();

    setState(() {
      role = snap['role'];
    });

    // if (role == 'user') {
    //   navigateNext(const HomeScreen());
    // } else if (role == 'admin') {
    //   navigateNext(const AdminScreen());
    // }
  }

  void navigateNext(Widget route) {
    Timer(const Duration(milliseconds: 500), () {
      Navigator.pushReplacement(
          context, MaterialPageRoute(builder: (context) => route));
    });
  }

  // @override
  // Widget build(BuildContext context) {
  //   return Scaffold(
  //       body: Center(
  //     child: Column(
  //       mainAxisAlignment: MainAxisAlignment.center,
  //       children: const [
  //         Text('Welcome to my project'),
  //       ],
  //     ),
  //   ));
  // }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          if (role == 'user') const HomeScreen(),
          if (role == 'admin') const AdminScreen(),
        ],
      ),
    ));
  }
}

以下是异常错误:

Exception has occurred.
"Error: Cannot hit test a render box that has never been laid out.
The hitTest() method was called on this RenderBox: RenderStack#197ec NEEDS-LAYOUT NEEDS-PAINT:
  creator: Stack ← _FloatingActionButtonTransition ← MediaQuery ← LayoutId-[<_ScaffoldSlot.floatingActionButton>] ← CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#c955e ink renderer] ← NotificationListener<LayoutChangedNotification> ← PhysicalModel ← AnimatedPhysicalModel ← ⋯
  parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.floatingActionButton
  constraints: MISSING
  size: MISSING
  alignment: Alignment.centerRight
  textDirection: ltr
  fit: loose
Unfortunately, this object's geometry is not known at this time, probably because it has never been laid out. This means it cannot be accurately hit-tested.
If you are trying to perform a hit test during the layout phase itself, make sure you only hit test nodes that have completed layout (e.g. the node's children, after their layout() method has been called).
    at Object.throw_ [as throw] (http://localhost:61527/dart_sdk.js:5061:11)

下面是调试错误:

Launching lib\main.dart on Chrome in debug mode...
This app is linked to the debug service: ws://127.0.0.1:51157/0tP91b-9bJU%3D/ws
Debug service listening on ws://127.0.0.1:51157/0tP91b-9bJU=/ws
 Running with sound null safety
Connecting to VM Service at ws://127.0.0.1:51157/0tP91b-9bJU=/ws

════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.

This probably means that it is a render object that tries to be as big as possible, but it was put inside another render object that allows its children to pick their own size.
The nearest ancestor providing an unbounded height constraint is: RenderFlex#5be33 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
The constraints that applied to the RenderCustomMultiChildLayoutBox were: BoxConstraints(0.0<=w<=681.0, 0.0<=h<=Infinity)
The exact size it was given was: Size(681.0, Infinity)

See https://flutter.dev/docs/development/ui/layout/box-constraints for more information.

The relevant error-causing widget was
Scaffold
When the exception was thrown, this was the stack
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49  throw_
packages/flutter/src/rendering/box.dart 2205:9                                                                             <fn>
packages/flutter/src/rendering/box.dart 2298:14                                                                            debugAssertDoesMeetConstraints
packages/flutter/src/rendering/box.dart 1991:7                                                                             <fn>
packages/flutter/src/rendering/box.dart 1992:14                                                                            set size
packages/flutter/src/rendering/custom_layout.dart 403:5                                                                    performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/proxy_box.dart 1388:11                                                                      performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/layout_helper.dart 56:10                                                                    layoutChild
packages/flutter/src/rendering/flex.dart 829:43                                                                            [_computeSizes]
packages/flutter/src/rendering/flex.dart 931:32                                                                            performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/shifted_box.dart 437:7                                                                      performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/custom_layout.dart 171:10                                                                   layoutChild
packages/flutter/src/material/scaffold.dart 1097:7                                                                         performLayout
packages/flutter/src/rendering/custom_layout.dart 240:7                                                                    [_callPerformLayout]
packages/flutter/src/rendering/custom_layout.dart 404:14                                                                   performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/proxy_box.dart 1388:11                                                                      performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 3420:14                                                                      performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/rendering/proxy_box.dart 116:7                                                                        performLayout
packages/flutter/src/rendering/object.dart 1858:7                                                                          layout
packages/flutter/src/widgets/overlay.dart 745:14                                                                           performLayout
packages/flutter/src/rendering/object.dart 1713:7                                                                          [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 885:17                                                                          flushLayout
packages/flutter/src/rendering/binding.dart 453:19                                                                         drawFrame
packages/flutter/src/widgets/binding.dart 883:13                                                                           drawFrame
packages/flutter/src/rendering/binding.dart 319:5                                                                          [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1143:15                                                                        [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1080:9                                                                         handleDrawFrame
packages/flutter/src/scheduler/binding.dart 996:5                                                                          [_handleDrawFrame]
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/platform_dispatcher.dart 1003:13           invoke
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/platform_dispatcher.dart 157:5             invokeOnDrawFrame
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine.dart 440:45                                <fn>
The following RenderObject was being processed when the exception was fired: RenderCustomMultiChildLayoutBox#95e25 relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderCustomMultiChildLayoutBox#95e25 relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
    parentData: <none> (can use size)
    constraints: BoxConstraints(0.0<=w<=681.0, 0.0<=h<=Infinity)
    size: Size(681.0, Infinity)
    child 1: RenderPositionedBox#0a91e NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.body
        constraints: MISSING
        size: MISSING
        alignment: Alignment.center
        textDirection: ltr
        widthFactor: expand
        heightFactor: expand
        child: RenderFlex#1cdfb NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
            parentData: offset=Offset(0.0, 0.0)
            constraints: MISSING
            size: MISSING
            direction: vertical
            mainAxisAlignment: center
            mainAxisSize: max
            crossAxisAlignment: center
            verticalDirection: down
            child 1: RenderParagraph#768de NEEDS-LAYOUT NEEDS-PAINT
                parentData: offset=Offset(0.0, 0.0); flex=null; fit=null
                constraints: MISSING
                size: MISSING
                textAlign: start
                textDirection: ltr
                softWrap: wrapping at box width
                overflow: clip
                locale: en_US
                maxLines: unlimited
                text: TextSpan
                    debugLabel: (englishLike body1 2014).merge(blackRedmond bodyText2)
                    inherit: false
                    color: Color(0xdd000000)
                    family: Segoe UI
                    size: 14.0
                    weight: 400
                    baseline: alphabetic
                    decoration: TextDecoration.none
                    "You have logged in Successfuly"
            child 2: RenderConstrainedBox#f5889 NEEDS-LAYOUT NEEDS-PAINT
                parentData: offset=Offset(0.0, 0.0); flex=null; fit=null
                constraints: MISSING
                size: MISSING
                additionalConstraints: BoxConstraints(0.0<=w<=Infinity, h=50.0)
            child 3: RenderConstrainedBox#6f662 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                parentData: offset=Offset(0.0, 0.0); flex=null; fit=null
                constraints: MISSING
                size: MISSING
                additionalConstraints: BoxConstraints(w=150.0, h=60.0)
                child: RenderSemanticsAnnotations#68b39 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                    parentData: <none>
                    constraints: MISSING
                    semantic boundary
                    size: MISSING
    child 2: RenderStack#197ec NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.floatingActionButton
        constraints: MISSING
        size: MISSING
        alignment: Alignment.centerRight
        textDirection: ltr
        fit: loose
        child 1: RenderTransform#402cb NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
            parentData: not positioned; offset=Offset(0.0, 0.0)
            constraints: MISSING
            size: MISSING
            transform matrix: [0] 0.0,0.0,0.0,0.0
[1] 0.0,0.0,0.0,0.0
[2] 0.0,0.0,1.0,0.0
[3] 0.0,0.0,0.0,1.0
            origin: null
            alignment: Alignment.center
            textDirection: ltr
            transformHitTests: true
            child: RenderTransform#03a78 NEEDS-LAYOUT NEEDS-PAINT
                parentData: <none>
                constraints: MISSING
                size: MISSING
                transform matrix: [0] 0.7,0.7,0.0,0.0
[1] -0.7,0.7,0.0,0.0
[2] 0.0,0.0,1.0,0.0
[3] 0.0,0.0,0.0,1.0
                origin: null
                alignment: Alignment.center
                textDirection: ltr
                transformHitTests: true
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════
_RenderInkFeatures object was given an infinite size during layout.
The relevant error-causing widget was
Scaffold
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════
RenderPhysicalModel object was given an infinite size during layout.
The relevant error-causing widget was
Scaffold
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by Infinity pixels on the bottom.
The relevant error-causing widget was
Column
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by scheduler library ═════════════════════════════════
Cannot hit test a render box that has never been laid out.
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by scheduler library ═════════════════════════════════
Assertion failed:
!_debugDuringDeviceUpdate
is not true

════════════════════════════════════════════════════════════════════════════════

截屏: 在此处输入图像描述

标签: firebasefluttergoogle-cloud-firestorefirebase-authentication

解决方案


也许您可能已经修复,但让我分享我的解决方案,您可以在此升级。

SplashScreen 页面和模型类

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_dynamic_links/admin_page.dart';
    import 'package:flutter_dynamic_links/user_page.dart';

    class SplashScreen extends StatefulWidget {
      final SplashScreenModel model;
      const SplashScreen({
        Key? key,
        required this.model,
      }) : super(key: key);

      @override
      State<SplashScreen> createState() => _SplashScreenState();
    }

    class _SplashScreenState extends State<SplashScreen> {
      @override
      void initState() {
        super.initState();
        checkRoleAndNavigate();
      }

      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text('You can show loading indicator or App logo'),
        );
      }

      Future<void> checkRoleAndNavigate() async {
        final Role role = await widget.model.init();
        if (role == Role.admin) {
          Navigator.pushReplacement(
              context, MaterialPageRoute(builder: (_) => AdminPage()));
        } else if (role == Role.user) {
          Navigator.pushReplacement(
              context, MaterialPageRoute(builder: (_) => UserPage()));
        }
      }
    }

    class SplashScreenModel {
      //as it takes little time to check no need timer
      Future<Role> init() async {
        final user = FirebaseAuth.instance.currentUser;
        final snap = await FirebaseFirestore.instance
            .collection('users')
            .doc(user!.uid)
            .get();
        final role = snap['role'];
        if (role == 'user') {
          return Role.user;
        } else {
          return Role.admin;
        }
      }
    }

    enum Role { user, admin }

用户页面

    import 'package:flutter/material.dart';

    class UserPage extends StatelessWidget {
      const UserPage({Key? key}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text('User Page'),
        );
      }
    }

管理页面

    import 'package:flutter/material.dart';

    class AdminPage extends StatelessWidget {
      const AdminPage({Key? key}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text('Admin Page'),
        );
      }
    }

==================================================== ====

显示 5 秒或其他东西的飞溅

        checkRoleAndNavigate() {
        Future.delayed(Duration(seconds: 5)).then((value) async {
          final Role role = await widget.model.init();
          if (role == Role.admin) {
            Navigator.pushReplacement(
                context, MaterialPageRoute(builder: (_) => AdminPage()));
          } else if (role == Role.user) {
            Navigator.pushReplacement(
                context, MaterialPageRoute(builder: (_) => UserPage()));
          }
        });
      }

推荐阅读