【发布时间】:2020-02-21 22:21:53
【问题描述】:
我正在尝试使用 BLoC 模式实现 Firebase 电话身份验证。
这是我的集体课
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final AuthProvider authProvider;
AuthBloc({this.authProvider}) : assert(authProvider!= null);
@override
AuthState get initialState => Uninitialized();
@override
Stream<AuthState> mapEventToState(AuthEvent event) async* {
if (event is AppLaunched) {
yield* _mapAppLaunchedToState();
} else if(event is OtpRequested) {
yield* _mapOtpRequestedToState();
} else if (event is LoggedIn) {
yield* _mapLoggedInToState();
} else if (event is LoggedOut) {
yield* _mapLoggedOutToState();
}
}
Stream<AuthState> _mapAppLaunchedToState() async* {
try {
final isSignedIn = await authProvider.isLoggedIn();
if (isSignedIn) {
final name = userProvider.firebaseUser;
yield Authenticated(name);
} else {
yield Unauthenticated();
}
} catch (_) {
yield Unauthenticated();
}
}
Stream<AuthState> _mapOtpRequestedTostate() async* {
yield AuthInProgress();
try {
FirebaseUser firebaseUser = await authProvider.verifyPhone();
if (firebaseUser != null) {
yield Authenticated(firebaseUser);
} else {
yield Unauthenticated();
}
} catch(_, stacktrace) {
yield Unauthenticated();
}
}
Stream<AuthState> _mapLoggedInToState() async* {
yield Authenticated(userProvider.firebaseUser);
}
Stream<AuthState> _mapLoggedOutToState() async* {
yield Unauthenticated();
authProvider.signOutUser();
}
}
这是 AuthProvider
class AuthProvider extends BaseAuthProvider {
String _verificationId;
FirebaseUser user;
final FirebaseAuth _firebaseAuth;
AuthProvider(
{FirebaseAuth firebaseAuth})
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
@override
Future<FirebaseUser> verifyPhone() async {
final PhoneVerificationCompleted verificationCompleted =
(AuthCredential phoneAuthCredential) async {
user = (await _firebaseAuth.signInWithCredential(phoneAuthCredential)).user;
};
final PhoneVerificationFailed verificationFailed =
(AuthException authException) {
print(
'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}');
};
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
_verificationId = verificationId;
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) {
_verificationId = verificationId;
};
await _firebaseAuth.verifyPhoneNumber(
phoneNumber: _phoneNumberProvider.number,
timeout: const Duration(seconds: 5),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
return user;
}
Future<FirebaseUser> signInWithPhone() async {
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: _verificationId,
smsCode: _otpProvider.number,
);
final FirebaseUser user =
(await _firebaseAuth.signInWithCredential(credential)).user;
final FirebaseUser currentUser = await _firebaseAuth.currentUser();
assert(user.uid == currentUser.uid);
if (user != null) {
return currentUser;
} else {
return null;
}
}
@override
Future<void> signOutUser() async {
return Future.wait([_firebaseAuth.signOut()]); // terminate the session
}
@override
Future<FirebaseUser> getCurrentUser() async {
return await _firebaseAuth.currentUser(); //retrieve the current user
}
@override
Future<bool> isLoggedIn() async {
final user =
await _firebaseAuth.currentUser(); //check if user is logged in or not
return user != null;
}
@override
void dispose() {}
}
当来自 AuthBloc 的 verifyPhone 被调用时,它会异步执行,然后又会调用再次异步的 mcallbacks。所以 _mapOtpRequestedToState() 将在我们从 AuthProvider 取回 FirebaseUser 之前完成。因此没有产生身份验证状态,并且用户没有登录。
需要帮助!!!
【问题讨论】:
标签: firebase flutter async-await firebase-authentication bloc