当前位置: 首页 > 知识库问答 >
问题:

FirebaseAuth.instance。userChanges流在页面重新加载后不发出登录用户(web)

濮君植
2023-03-14

在Flutter Web上,来自FirebaseAuth实例的userChanges流在页面重新加载后从不发送登录用户。相反,它只发出null。在下面的例子中,应用程序在加载页面上卡住了。

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/loading',
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case '/error':
            return MaterialPageRoute(builder: (_) => ErrorScreen());
          case '/loading':
            return MaterialPageRoute(builder: (_) => LoadingScreen());
          case '/signin':
            return MaterialPageRoute(builder: (_) => SignInScreen());
          case '/welcome':
            return MaterialPageRoute(builder: (_) => WelcomeScreen());
          default:
            return MaterialPageRoute(
                builder: (_) => Center(child: Text('Unknown route')));
        }
      },
    );
  }
}

class ErrorScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: Text('An error occurred.'),
      ),
    );
  }
}

class LoadingScreen extends StatefulWidget {
  @override
  _LoadingScreenState createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  @override
  void initState() {
    init();
    super.initState();
  }

  init() async {
    try {
      await Firebase.initializeApp();
      if (kDebugMode) {
        await FirebaseAuth.instance.useEmulator('http://localhost:1001');
      }

      final preferences = await SharedPreferences.getInstance();
      bool signedIn = preferences.getBool('IS_SIGNED_IN') ?? false;

      String landingPath = '/signin';

      if (signedIn) {
        landingPath = '/welcome';
        // Wait for the userChanges to emit a non-null element.
        await FirebaseAuth.instance
            .userChanges()
            .firstWhere((user) => user != null);
      }

      Navigator.of(context).pushReplacementNamed(landingPath);
    } catch (error) {
      print(error);
      Navigator.of(context).pushReplacementNamed('/error');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: Text('Loading...'),
      ),
    );
  }
}

class SignInScreen extends StatelessWidget {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            TextField(
              controller: _emailController,
              decoration: InputDecoration(labelText: 'Email address'),
            ),
            TextField(
              decoration: InputDecoration(labelText: 'Password'),
              obscureText: true,
              controller: _passwordController,
            ),
            ElevatedButton(
              onPressed: () => _submit(context),
              child: Text('SIGN IN'),
            ),
          ],
        ),
      ),
    );
  }

  void _submit(BuildContext context) async {
    final email = _emailController.text;
    final password = _passwordController.text;
    FirebaseAuth.instance
        .signInWithEmailAndPassword(email: email, password: password)
        .then((credential) async {
      final preferences = await SharedPreferences.getInstance();
      await preferences.setBool('IS_SIGNED_IN', true);

      Navigator.of(context).pushReplacementNamed('/welcome');
    });
  }
}

class WelcomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Text('Welcome!'),
            ElevatedButton(
              onPressed: () => _signOut(context),
              child: Text('SIGN OUT'),
            )
          ],
        ),
      ),
    );
  }

  void _signOut(BuildContext context) {
    FirebaseAuth.instance.signOut().then((_) async {
      final preferences = await SharedPreferences.getInstance();
      await preferences.setBool('IS_SIGNED_IN', false);

      Navigator.of(context).pushReplacementNamed('/signin');
    });
  }
}

如果有帮助的话,我在我的index.html文件中使用的是Firebase Javascript库的8.3.0版本。

我是不是遗漏了什么?

共有1个答案

邢炯
2023-03-14

事实证明,上面的代码是正确的。问题是仿真器。注释这些代码行使应用程序的行为符合预期:

if (kDebugMode) {
  FirebaseAuth.instance.useEmulator('http://localhost:1001');
}

我已经在FlutterFire的repo上提交了一份关于这个模拟器问题的错误报告。

 类似资料:
  • 当我使用Parse时,SDK似乎会将会话数据存储在本地,用户在刷新页面(或退出移动应用程序)后无需再次登录。Firebase/Angularfire的情况似乎并非如此;每次我刷新我的网页,身份验证数据都会得到很多。这似乎是非常基本和重要的功能,我会很惊讶Firebase的优秀人员还没有实现。我错过什么了吗? 完整性;这是我在应用程序中的代码。run():

  • 嗨,伙计们,我是一个平均堆栈开发的初学者,我试图在注销后刷新页面。我尝试了;但它不起作用告诉我可能的代码页面重载在这种情况下

  • 记录器文件中的日志- org.springframework.Security.Access.event.loggerlistener-安全授权失败,原因是:org.springframework.Security.Access.accessdeniedexception:访问被拒绝;通过身份验证的主体:org.springframework.security.authentication.ano

  • 我想在注销后刷新/重新加载页面(屏幕上的消息在5秒钟内可见)。当前代码不会刷新它,所以我仍然在标题中看到用户名,而不是像登录按钮这样的东西。 我已经检查了这篇文章,但没有什么变化。

  • 问题内容: 我有一个带有php include的Div Tag,该div用来填充该信息,我想要做的是使它每隔15秒调用一次,以便它可以在那里更新信息,而不必重新加载整个网页。我试图用JavaScript / jQuery做到这一点,但似乎无法正常工作 这是我在搜索一些内容后所拥有的,然后发生的是,它加载了Small.php,但不会每15秒刷新一次或更新信息。 请帮忙! 我应该添加所有应显示的php

  • 问题内容: 我想设置我的网站,以便如果用户点击该页面并且他们已经登录,它将把他们重定向到主页。如果未登录,它将正常显示。由于登录代码内置在Django中,我该怎么做? 问题答案: 我假设你当前正在使用内置的登录视图, 或你网址中的类似内容。 你可以编写包含默认视图的登录视图。它将检查用户是否已经登录,如果已经登录则重定向,否则使用默认视图。 就像是: 当然可以相应地更改你的网址: