我有一个WelcomeScreen,其中包含注册和登录和HomeScreen,我想在用户登录后重定向.为了管理身份验证数据,我创建了一个具有static个属性和方法的auth.dart,这样我就可以跨具有相同数据的所有页面访问它们.

import 'package:firebase_auth/firebase_auth.dart';

class Auth {

  static final auth = FirebaseAuth.instance;

  static Future<void> logout() async {
    await auth.signOut();
  }

  static Future<void> loginUser(String userEmail, String userPassword) async {
    await auth.signInWithEmailAndPassword(email: userEmail, password: userPassword);
  }

  static Future<FirebaseUser> getCurrentUser() async {
    return await auth.currentUser();
  }
}

main.dart文件中,我使用StreamBuilder根据更改的身份验证数据更改当前屏幕.我从this answer得到StreamBuilder码.

home: StreamBuilder<FirebaseUser>(
  stream: Auth.auth.onAuthStateChanged,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return HomeScreen();
    } else {
      return WelcomeScreen();
    }
  },
),

在我的登录屏幕中,我使用以下代码触发登录:

Future<void> login() async {
    ...

    try {
      await Auth.loginUser(userEmail, userPassword);
      var user =  await Auth.getCurrentUser();
      print(user.displayName); // This works
    } catch (error) {
      print(error.message);
    }
  }

我不知道我正在使用的静电方法是否是处理Firebase身份验证的正确方式,但它似乎起作用了.登录后,我可以显示登录用户的名称,但main.dart中的StreamBuilder没有反映更新的身份验证数据,即没有更改页面.

是因为静电的办法,还是执行百人制出了什么问题?

推荐答案

Null safe code (using provider)

enter image description here


Full code:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(
    ChangeNotifierProvider<AuthModel>(
      create: (_) => AuthModel(),
      child: MaterialApp(
        home: Consumer<AuthModel>(
          builder: (_, auth, __) => auth.isSignedIn ? HomePage() : WelcomePage(),
        ),
      ),
    ),
  );
}

class WelcomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('WelcomePage')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => LoginPage())),
          child: Text('Go to Login Page'),
        ),
      ),
    );
  }
}

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Login Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final model = context.read<AuthModel>();
            await model.signIn(email: 'test@test.com', password: 'test1234');
            Navigator.pop(context);
          },
          child: Text('Login'),
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('HomePage')),
      body: Center(
        child: FloatingActionButton.extended(
          onPressed: () async {
            final model = context.read<AuthModel>();
            await model.signOut();
          },
          label: Text('Log out'),
        ),
      ),
    );
  }
}

class AuthModel extends ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  bool get isSignedIn => _auth.currentUser != null;

  Future<void> signIn({required String email, required String password}) async {
    await _auth.signInWithEmailAndPassword(email: email, password: password);
    notifyListeners();
  }

  Future<void> signOut() async {
    await _auth.signOut();
    notifyListeners();
  }
}

Dart相关问答推荐

有没有办法否定IF条件中的模式大小写匹配?

dart中如何从xpath获取属性值?

您如何在元素中设置自定义元素标签的样式?

AppLifcycleState.didChangeLifecycleState( ) 函数在应用程序进入前台或后台时不被调用

Asset图像作为Card背景,Flutter 中顶部有文本

Flutter:可重新排序和动画的 ListView - 有什么 idea 吗?

如何在Flutter中正确显示Snackbar?

在向下滚动时隐藏底部导航栏,反之亦然

Flutter类继承

如何使 FadeInImage 循环?

Dart:默认 gitignore?

Dart Nodejs 和 Socketio

Dart 转换列表的每个元素

轻松判断数字是否在 Dart 的给定范围内?

Cancel stream onData

dart:io 中带有 json 内容类型的 Http POST 请求

如何在 Dart SDK 0.4+ 中使用 setInterval/setTimeout

Dart 如何匹配然后替换正则表达式

Dart 中的 urlencoding

在 Dart 中将类型化函数作为参数传递