I'm building a phone authentication ui (OTP) using firebase_auth
library with BLoC pattern (a bit of an overkill for this ui, but the whole project is in BLoC, so). I'm processing the authentication within the BLoC, as such:
@override
Stream<PhoneAuthState> mapEventToState(PhoneAuthEvent event) async* {
....
else if(event is PhoneNumberSubmittedEvent) yield* _handlePhoneNumberSubmittedEvent(event);
....
}
Stream<PhoneAuthState> _handlePhoneNumberSubmittedEvent(PhoneNumberSubmittedEvent event) async*{
yield SendingCodeState();
await Firebase.initializeApp();
var firebaseAuth = FirebaseAuth.instance;
await firebaseAuth.verifyPhoneNumber(
phoneNumber: _buildPhoneNumber(),
timeout: Duration(seconds: 0),
verificationCompleted: (firebaseUser) {},
codeAutoRetrievalTimeout: (String verificationId) {},
// Relevant code
codeSent: (id, [forceResendingToken]) =>
emit(_codeSentState(id, forceResendingToken)),
verificationFailed: (error) =>
emit(_verificationFailedState(error)),
);
}
Because the results of my _codeSentState
and _verificationFailedState
functions cannot be yielded from within the handlePhoneNumberSubmittedEvent
method, I used emit
(which is actually working fine).
However, as I was looking through BLoC docs, I found that emit
is @protected
, and the docs stating:
[emit] should never be used outside of tests.
So I have three questions:
emit
be used outside of tests?emit
? (other than yielding in response to events in mapEventToState
)yield
the result of a function that is passed as a parameter to a method/constructor call? (in my case, is there a way to yield
the results of _codeSentState
and/or _verificationFailedState
that are called within firebaseAuth.verifyPhoneNumber.codeSent
and firebaseAuth.verifyPhoneNumber.verificationFailed
respectively?)In flutter_bloc
version 8.0.0, this issue was resolved. The method mapEventToState
was replaced with the more efficient on<Event>
to respond to events. on
method provides an emitter
as a parameter to its callback, which can be used to emit states as needed. In other words, the code I mentioned in OP can now be written as follows
// constructor
MyBloc() : super(MyInitialState) {
on<PhoneNumberSubmittedEvent>((event, emit) async {
emit(SendingCodeState());
await Firebase.initializeApp();
var firebaseAuth = FirebaseAuth.instance;
await firebaseAuth.verifyPhoneNumber(
phoneNumber: _buildPhoneNumber(),
timeout: Duration(seconds: 0),
verificationCompleted: (firebaseUser) {},
codeAutoRetrievalTimeout: (String verificationId) {},
codeSent: (id, [forceResendingToken]) =>
emit(_codeSentState(id, forceResendingToken)),
verificationFailed: (error) =>
emit(_verificationFailedState(error)),
);
});
}