大家。我是 Flutter 和 BLoC 模式的新手。
我需要实现联系人页面,所以我创建了事件 GetContacts 并将其传递给 context.read().add() 之后,我将此事件调用到联系人屏幕的 initState() 中。
这是我的活动:
abstract class ContactEvent extends Equatable {
const ContactEvent([List props = const []]) : super();
}
class GetContacts extends ContactEvent {
const GetContacts() : super();
@override
List<Object> get props => [];
}
这是我的集团:
class ContactsBloc extends Bloc<ContactEvent, ContactsState> {
final ContactsRepo contactsRepo;
ContactsBloc({required this.contactsRepo}) : super(ContactInitial());
@override
Stream<ContactsState> mapEventToState(ContactEvent event,) async* {
yield ContactsLoading();
//
// if (event is UpdatePhoto) {
// yield PhotoLoading();
//
// print("LOADING STARTED");
//
// final photo = await contactsRepo.updatePhoto(event.identifier, event.photo);
// print("LOADING FINISHED");
//
// yield PhotoLoaded(photo: photo);
// }
if (event is GetContacts) {
print("get contacts photoBloc");
try {
final contacts = await contactsRepo.getContacts();
yield ContactsLoaded(contacts);
} on AccessException {
yield ContactsError();
}
}
}
}
效果很好,联系人页面会按预期呈现联系人。
[联系人屏幕][1] [1]:https://i.stack.imgur.com/Gx3JA.png
但后来我决定实施新功能:当用户点击任何联系人时,他会被要求更改其照片。 如果我正确理解 BLoC 模式,那么如果我想改变我的状态,我需要创建新事件。然后我创建了新的操作 UpdatePhoto 并将它传递到同一个 Bloc 中,正如它在代码的第二部分(在注释中)所示。正是在那里,我遇到了对架构扩展的误解。此操作不应返回 ContactsLoaded 状态,因此当我尝试将其捕获到我的另一个 bloc 构建器中时,它破坏了我之前捕获 GetContact 事件的 bloc 构建器。
联系状态:
abstract class ContactsState extends Equatable {
const ContactsState([List props = const []]) : super();
}
// class PhotoLoading extends PhotoState {
// @override
// List<Object?> get props => [];
// }
//
// class PhotoLoaded extends PhotoState {
// final Uint8List photo;
// const PhotoLoaded({required this.photo});
// @override
// List<Object?> get props => [photo];
// }
class ContactInitial extends ContactsState {
@override
List<Object> get props => [];
}
class ContactsLoading extends ContactsState {
@override
List<Object> get props => [];
}
class ContactsLoaded extends ContactsState {
final List<MyContact> contacts;
ContactsLoaded(this.contacts) : super([contacts]);
@override
List<Object> get props => [contacts];
}
class ContactsError extends ContactsState {
@override
List<Object?> get props => [];
}
问题:如果我想创建新事件(例如 UpdatePhoto),该事件不应该返回我之前在同一块中捕获的状态,那么我需要为此目的创建新块并通过 multiProvider 覆盖我的屏幕?
答案 0 :(得分:2)
您还应该发布您的 ContactState 代码。
然而,你并不一定需要一个新的 Bloc。这一切都取决于您要实现的目标。
我想当你 yield PhotoLoading()
你想要展示一个加载器时。
但是,当您更新照片时,如果我了解您要实现的目标,您应该再次使用 yield ContactsLoaded(contacts)
或 add(GetContacts())
而不是 yield PhotoLoaded(photo: photo)
生成更新的联系人列表。
如果您想显示确认消息,您可以保持 PhotoLoaded 状态,但您需要在构建 UI 时考虑到 bloc 可能发出的不同状态。
请记住,在 BloC 架构中,事件可以连续产生多个状态,而 UI 决定是否以及如何对每个状态做出反应。
答案 1 :(得分:1)
我想在 BlocBuilder 中使用可选参数 buildWhen 是避免为每个事件创建新 bloc 的最佳方法。