最近一直在将旧代码转换成BLOC 8.1版本,遇到了下一个问题。该应用程序是多线程的,并且 mapEventToState 方法用完了流,重要的是,yield 使用了。 例子:
BlocBuilder<NewsBloc, NewsState>(builder: (context, state) {
switch (state.status) {
case NewsStatus.failure:
return const Center(
child: Text('FAILD'));
case NewsStatus.newMessage:
return messageList(objNews);
case NewsStatus.success:
return messageList(objNews);
default:
return const Center(child: CircularProgressIndicator());
}
}
问题是他 on(mapEventToState) 需要一个 Future 而我需要它是带有 yield 的流。
新闻集团
class NewsBloc extends Bloc<NewsEvent, NewsState> {
NewsBloc(...)
super(NewsState()) {
on<NewsEvent>(mapEventToState);
}
@override
Stream<NewsState> mapEventToState(NewsEvent event) async* {
if (event is NewsInitial) {
yield await mapNewsInitialToState(state);
}
if (event is NewsFetched) {
yield await _mapNewsFetchedToState(state);
}
if (event is MessageReceived) {
yield await _mapMessageReceivedToState(state, event);
}
if (event is NewsClear) {
yield await mapNewsClearToState(state);
}
if (event is MessageRead) {
yield await mapMessageReadToState(state, event);
}
}
}
Future<ChatListState> mapNewsInitialToState(NewsState state) async {
try {
final rooms = await services!.getRoomsList();
return state.copyWith(
status: NewsStatus.success,
rooms: rooms,
state: state
);
} catch (e, s) {
print('$e, stacktrace: $s');
return state.copyWith(status: NewsStatus.failure,state: state);
}
}
新闻状态
enum NewsStatus { initial, success, failure, newMessage }
class NewsState extends Equatable {
NewsStatus? status;
List<NewsRoom>? rooms;
bool? hasReachedMax;
bool? isNew;
NewsState({
this.status = NewsStatus.initial,
this.rooms = const <NewsRoom>[],
this.hasReachedMax = false,
this.isNew = false,
});
NewsState copyWith({
@required NewsStatus? status,
@required List<NewsRoom>? rooms,
@required bool? hasReachedMax,
@required bool? isNew,
required NewsState state
}) {
state.status = status ?? this.status ;
state.rooms = rooms ?? this.rooms;
state.hasReachedMax = hasReachedMax ?? this.hasReachedMax;
state.isNew = isNew ?? this.isNew ;
return state;
}
@override
String toString() {
return '''NewsState { status: $status, hasReachedMax: $hasReachedMax, rooms: ${rooms!.length}, isNew: $isNew, }''';
}
@override
List<Object?> get props => [status, rooms, hasReachedMax, isNew];
}
class MessageReceivedState extends NewsState {
final ChatMessage? chatMessage;
MessageReceivedState({@required this.chatMessage});
@override
List<Object?> get props => [chatMessage];
}
有谁知道如何同时保持流,以便代码与 BLOC 8.1 一致?
BLoC 8 使用
Emitter
而不是带有 Stream
的 yield
s。尝试更改 mapEventToState
签名并将 yield
替换为 Emitter
调用。
大致应该是这样的:
void mapEventToState(
NewsEvent event,
Emitter<NewsState> emit,
) async {
if (event is NewsInitial) {
emit(await mapNewsInitialToState(state));
} else if (event is NewsFetched) {
emit(await _mapNewsFetchedToState(state));
} else if (event is MessageReceived) {
emit(await _mapMessageReceivedToState(state, event));
} else if (event is NewsClear) {
emit(await mapNewsClearToState(state));
} else if (event is MessageRead) {
emit(await mapMessageReadToState(state, event));
}
}