【问题标题】:Flutter Firebase Authentication: delay on startupFlutter Firebase 身份验证:启动延迟
【发布时间】:2024-05-20 18:45:01
【问题描述】:

我在应用程序中使用 Provider 和流 FirebaseAuth.instance.onAuthStateChanged 来决定在启动时重定向到哪里,但是虽然用户已经登录(从以前的启动),但应用程序在登录屏幕上启动并且几乎 1第二个稍后重定向到主页,它应该从第一刻开始。即使在飞行模式下也会发生这种情况。

我想知道有没有办法解决这个问题,即使不能一次显示主屏幕,我也不知道如何区分未登录的用户(null->登录屏幕) 和加载用户(null->加载屏幕)。

部分代码:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final DatabaseService db = DatabaseService();
  @override
  Widget build(BuildContext context) {
    return StreamProvider<FirebaseUser>.value(
      value: _auth.onAuthStateChanged,
      child: Consumer<FirebaseUser>(
        builder: (context, firebaseUser, child) {
          return MultiProvider(
            providers: [
              if (firebaseUser != null)
                ChangeNotifierProvider(create: (ctx) => CollectionState(firebaseUser)),
              StreamProvider<List<Collection>>.value(value: db.streamCollections(firebaseUser)),
            ],
            child: MaterialApp(
              title: 'My App',
              routes: {
                '/': (ctx) => LandingPage(),
                '/login': (ctx) => LoginPage(),
                '/emailSignIn': (ctx) => EmailSignInPage(),
                '/emailSignUp': (ctx) => EmailSignUpPage(),
                '/emailUnverified': (ctx) => EmailUnverifiedPage(),
                '/home': (ctx) => HomePage(),
                '/settings': (ctx) => Settings(),
              },
            ),
          );
        },
      ),
    );
  }
}

class LandingPage extends StatelessWidget {
  final DatabaseService _db = DatabaseService();
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<FirebaseUser>(context);
    final userCondition =
        user == null ? 'null' : user.isEmailVerified ? 'verifiedUser' : 'unverifiedUser';

    switch (userCondition) {
      case 'null':
        return LoginPage();
        break;
      case 'unverifiedUser':
        return EmailUnverifiedPage();
        break;
      case 'verifiedUser':
        return HomePage();
        break;
    }
  }
}

代码稍微简化了一点,我使用一个服务作为身份验证实例,仅此而已。

【问题讨论】:

  • 共享偏好
  • 感谢您的回复冥想。你能再解释一下吗?

标签: flutter firebase-authentication


【解决方案1】:

我知道我已经很晚了,但我已经有同样的问题好几个星期了,我终于弄明白了。

@ChinkySight 说得对,他说最好使用 StreamBuilder,主要是因为您可以访问 connectionState 属性。

存在延迟的原因是与流的连接没有完全建立。因此,在 ConnectionState.waiting 期间,返回一个像闪屏这样的小部件或只是一个容器。

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: FirebaseAuth.instance.onAuthStateChanged,
        builder: (_, snapshot) {
          // Added this line
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Container();
          }
          if (snapshot.data is FirebaseUser && snapshot.data != null) {
            return HomePage();
          }
          return LoginPage();
        });
  }
}

您甚至可以使用 Animated Switcher 为您的返回语句添加精美的动画

return StreamBuilder(
      stream: FirebaseAuth.instance.onAuthStateChanged,
      builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
        Widget widget;

        if (snapshot.connectionState == ConnectionState.waiting) {
          return Container();
        }

        switch (snapshot.hasData) {
          case (true):
            widget = HomePage();
            break;
          case (false):
            widget = LoginPage();
        }
        return Stack(
          children: <Widget>[
            Scaffold(
              backgroundColor: Colors.grey.shade200,
            ),
            AnimatedSwitcher(
              duration: Duration(milliseconds: 700),
              child: FadeTransition(
                  opacity: animation,
                  child: widget,
                ),
               );
              },
            )
          ],
        );
      },
    );

【讨论】:

  • 动画切换器不工作,所以把代码改成:return AnimatedSwitcher(duration: Duration(milliseconds: 300), child: widget, );
  • 这是一个错误。它的孩子应该是 FadeTransition。让我编辑代码。编辑:已编辑!!
【解决方案2】:

这适用于FlutterFire

Firebase 身份验证使您能够通过 溪流。一旦被调用,流会提供一个即时事件 用户当前的认证状态,然后提供后续的 身份验证状态更改时的事件。订阅 这些更改,请在 FirebaseAuth 上调用 authStateChanges() 方法 实例:

import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:flutter/material.dart';
import 'menu.dart';
import 'login.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:firebase_core/firebase_core.dart';

Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      runApp(
          MyApp()
        );
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitUp]);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'TestApp',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: 
        StreamBuilder<auth.User>(
          stream: auth.FirebaseAuth.instance.authStateChanges(),
          builder: (BuildContext context, AsyncSnapshot<auth.User> snapshot) { 
            if(snapshot.hasData) {
              print("data exists");
              return HomePage();
            }
            else {
              return LoginPage();
            }
          },
        )
    );
  }
}

【讨论】:

  • 这很漂亮