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);},); } }
关键变更说明
- AuthService的getCurrentUser:新版本把
onAuthStateChanged替换成了authStateChanges()方法,返回的Stream类型从FirebaseUser变成了User,我们只需要修改map里的参数类型即可,整体Stream的逻辑完全保留。 - Firebase初始化:新版本的Firebase必须先调用
Firebase.initializeApp(),所以在main函数里添加了初始化代码,这是硬性要求。 - 登录方法的类型变更:
signInWithEmailAndPassword返回的类型从AuthResult变成了UserCredential,但获取用户的方式还是result.user,所以只需要修改返回类型即可,不影响现有登录逻辑。 - 所有获取用户的代码完全不变:你原来的
final currentUser = Provider.of<MyUser>(context)和Wrapper里的用户判断逻辑,还有HomePage里获取uid的代码,都不需要做任何修改,完美兼容现有用法。
这样修改后,你的应用就能顺利升级到新版本的Firebase Auth,同时完全保留原来的状态管理逻辑。
内容的提问来源于stack exchange,提问作者Canada2000
相关产品推荐
相关产品推荐

