You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Firebase Auth从0.15升级到0.18并保留StreamProvider方案咨询

升级Firebase Auth到^0.18.3并保留StreamProvider的完整解决方案

我帮你整理了从firebase_auth: ^0.15.5+3升级到^0.18.3的全部修改,完全保留你现有StreamProvider的用法和Provider.of<MyUser>(context)获取用户的逻辑,下面是完整的修改后的代码和关键说明:

第一步:更新pubspec.yaml

新版本的Firebase Auth依赖firebase_core,所以需要添加并更新版本:

name: myApp
environment:
  sdk: ">=2.7.0 <3.0.0"
dependencies:
  flutter:
    sdk: flutter
  # **** FIREBASE ****
  firebase_auth: ^0.18.3
  provider: ^4.0.5
  firebase_core: ^0.5.3  # 新版本必须添加这个依赖
dev_dependencies:
  flutter_test:
    sdk: flutter
flutter:
  uses-material-design: true
  assets:
    - assets/

第二步:修改核心代码(main.dart)

下面是修改后的完整代码,关键变更我用注释标出来了:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart'; // 新增导入

void main() async {
  // 新增:初始化Firebase必须的代码
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

//******************************************
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 这里完全保留原来的写法,不用改
    return StreamProvider<MyUser>.value(
      value: AuthService().getCurrentUser,
      child: MaterialApp(
        title: 'MyApp',
        home: Wrapper(),),);}
}

//******************************************
class Wrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 这里获取用户的方式完全不变
    final currentUser = Provider.of<MyUser>(context);
    if (currentUser == null) {return SignIn();} else {return HomePage();}}
}

//******************************************
class MyUser {
  String uid;
  MyUser({this.uid ,});
}

//******************************************
class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  
  // 关键修改1:用authStateChanges()替代onAuthStateChanged
  Stream<MyUser> get getCurrentUser {
    return _auth.authStateChanges().map((User user) => _refereeFromFirebaseUser(user));
  }
  
  // 关键修改2:参数类型从FirebaseUser换成User
  MyUser _refereeFromFirebaseUser(User _authUser) {
    return (_authUser != null) ? MyUser(uid: _authUser.uid) : null;
  }
  
  // 关键修改3:返回类型从AuthResult换成UserCredential,获取user的方式不变
  Future<UserCredential> signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
      User user = result.user;
      return result;
    } catch (error) {
      print(error.toString());
      return null;}
  }
  
  Future signOut() async {
    try {return await _auth.signOut();} catch (error) {print(error.toString());return null;}
  }
}

//******************************************
class HomePage extends StatelessWidget {
  final AuthService _auth = AuthService();
  @override
  Widget build(BuildContext context) {
    // 这里获取uid的方式完全保留
    final currentUser = Provider.of<MyUser>(context);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('MyApp2'), actions: <Widget>[FlatButton.icon(icon: Icon(Icons.person), label: Text('logout'), onPressed: () async {await _auth.signOut();},), ],),
        body: Text("My ID is ${currentUser.uid}"),
      ),);
  }
}

//******************************************
class SignIn extends StatefulWidget {
  @override
  _SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
  final AuthService _auth = AuthService();
  final _formKey = GlobalKey<FormState>();
  String error = '';
  String email ;
  String password ;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Form(key: _formKey, child: ListView(shrinkWrap: true, children: <Widget>[
        SizedBox(height: 60.0),
        emailField(),
        SizedBox(height: 8.0),
        passwordField(),
        SizedBox(height: 24.0),
        signInButton(),
        Text(error, style: TextStyle(color: Colors.red, fontSize: 16.0),),
      ],),),);}
  RaisedButton signInButton() {
    return RaisedButton(
      child: Text('Sign In'),
      onPressed: () async {
        if(_formKey.currentState.validate()) {
          dynamic result = await _auth.signInWithEmailAndPassword(email, password);
          if(result == null) {setState(() {error = 'Could not sign in with those credentials';});}}});
  }
  TextFormField passwordField() {
    return TextFormField(
      validator: (val) => val.length < 6 ? 'Enter a password 6+ chars long' : null,
      onChanged: (val) {setState(() => password = val);},);
  }
  TextFormField emailField() {
    return TextFormField(
      validator: (val) => val.isEmpty ? 'Enter an email' : null,
      onChanged: (val) {setState(() => email = val);},);
  }
}

关键变更说明

  1. AuthService的getCurrentUser:新版本把onAuthStateChanged替换成了authStateChanges()方法,返回的Stream类型从FirebaseUser变成了User,我们只需要修改map里的参数类型即可,整体Stream的逻辑完全保留。
  2. Firebase初始化:新版本的Firebase必须先调用Firebase.initializeApp(),所以在main函数里添加了初始化代码,这是硬性要求。
  3. 登录方法的类型变更:signInWithEmailAndPassword返回的类型从AuthResult变成了UserCredential,但获取用户的方式还是result.user,所以只需要修改返回类型即可,不影响现有登录逻辑。
  4. 所有获取用户的代码完全不变:你原来的final currentUser = Provider.of<MyUser>(context)和Wrapper里的用户判断逻辑,还有HomePage里获取uid的代码,都不需要做任何修改,完美兼容现有用法。

这样修改后,你的应用就能顺利升级到新版本的Firebase Auth,同时完全保留原来的状态管理逻辑。

内容的提问来源于stack exchange,提问作者Canada2000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:33:30