使用 bloc.emit 从一个 bloc 中发射状态
Emitting states from a bloc using bloc.emit
我正在使用具有 BLoC 模式的 firebase_auth
库进行 phone 身份验证 ui (OTP)(对于这个 ui,但整个项目都在 BLoC 中,所以)。我正在 BLoC 中处理身份验证,因此:
@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)),
);
}
因为我的 _codeSentState
和 _verificationFailedState
函数的结果无法从 handlePhoneNumberSubmittedEvent
方法中产生,所以我使用了 emit
(实际上工作正常)。
然而,当我浏览 BLoC 文档时,我发现 emit
是 @protected
,并且文档说明:
[emit] should never be used outside of tests.
所以我有三个问题:
- 为什么
emit
不能在测试之外使用?
- 是否有
emit
的替代方案? (除了响应 mapEventToState
中的事件而屈服)
- 有没有办法
yield
作为参数传递给 method/constructor 调用的函数的结果? (在我的例子中,有没有办法 yield
分别在 firebaseAuth.verifyPhoneNumber.codeSent
和 firebaseAuth.verifyPhoneNumber.verificationFailed
中调用的 _codeSentState
and/or _verificationFailedState
的结果? )
迁移到新版本的 bloc (>=6.0.0) wich bloc 与 cubit 集成,最佳实践是 bloc class 扩展 Cubit class 并使用 emit产生新状态的功能
在 bloc pub 页面上阅读更多内容:https://pub.dev/packages/flutter_bloc
更新
正如我在新版本中提到的,bloc 的作者使用 cubit 包迁移了 bloc,它添加了一种替代和简化的功能来控制应用程序的状态
如果你的 bloc class 正在扩展 bloc base class 所以你应该使用 (yilding state) 模式来控制状态但是如果你的 bloc 扩展了 cubit 你可以直接使用 emit 方法来控制你可以的状态在此处的文档中阅读它是 link:http://github.com/felangel/bloc/blob/master/packages/bloc/README.md
在 flutter_bloc
版本 8.0.0 中,此问题已解决。方法 mapEventToState
被替换为更有效的 on<Event>
来响应事件。 on
方法提供一个 emitter
作为其回调的参数,可用于根据需要发出状态。也就是说,我在OP中提到的代码现在可以这样写了
// 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)),
);
});
}
我正在使用具有 BLoC 模式的 firebase_auth
库进行 phone 身份验证 ui (OTP)(对于这个 ui,但整个项目都在 BLoC 中,所以)。我正在 BLoC 中处理身份验证,因此:
@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)),
);
}
因为我的 _codeSentState
和 _verificationFailedState
函数的结果无法从 handlePhoneNumberSubmittedEvent
方法中产生,所以我使用了 emit
(实际上工作正常)。
然而,当我浏览 BLoC 文档时,我发现 emit
是 @protected
,并且文档说明:
[emit] should never be used outside of tests.
所以我有三个问题:
- 为什么
emit
不能在测试之外使用? - 是否有
emit
的替代方案? (除了响应mapEventToState
中的事件而屈服) - 有没有办法
yield
作为参数传递给 method/constructor 调用的函数的结果? (在我的例子中,有没有办法yield
分别在firebaseAuth.verifyPhoneNumber.codeSent
和firebaseAuth.verifyPhoneNumber.verificationFailed
中调用的_codeSentState
and/or_verificationFailedState
的结果? )
迁移到新版本的 bloc (>=6.0.0) wich bloc 与 cubit 集成,最佳实践是 bloc class 扩展 Cubit class 并使用 emit产生新状态的功能 在 bloc pub 页面上阅读更多内容:https://pub.dev/packages/flutter_bloc
更新
正如我在新版本中提到的,bloc 的作者使用 cubit 包迁移了 bloc,它添加了一种替代和简化的功能来控制应用程序的状态 如果你的 bloc class 正在扩展 bloc base class 所以你应该使用 (yilding state) 模式来控制状态但是如果你的 bloc 扩展了 cubit 你可以直接使用 emit 方法来控制你可以的状态在此处的文档中阅读它是 link:http://github.com/felangel/bloc/blob/master/packages/bloc/README.md
在 flutter_bloc
版本 8.0.0 中,此问题已解决。方法 mapEventToState
被替换为更有效的 on<Event>
来响应事件。 on
方法提供一个 emitter
作为其回调的参数,可用于根据需要发出状态。也就是说,我在OP中提到的代码现在可以这样写了
// 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)),
);
});
}