事件管理 flutter bloc 模式
events management flutter bloc pattern
各位。我是 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 中。正是在那里,我遇到了对架构扩展的误解。此操作不应该 return 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),它不应该 return 我之前在同一个 bloc 捕获的状态,那么我需要为此目的创建新的 bloc 并且通过 multiProvider 覆盖我的屏幕?
您还应该 post 您的 ContactState 代码。
但是您不一定需要一个新的 Bloc。这完全取决于您要实现的目标。
我想当你 yield PhotoLoading()
你想展示一个装载机时。
但是当你更新照片时,如果我理解你想要实现的目标,你应该再次使用 yield ContactsLoaded(contacts)
或 add(GetContacts())
而不是 yield PhotoLoaded(photo: photo)
来生成更新的联系人列表。
如果你想显示一条确认消息,你可以保持你的 PhotoLoaded 状态,但你需要构建你的 UI 考虑到 bloc 可能发出的不同状态。
请记住,在 BloC 架构中,事件可以连续屈服于多个状态,UI 决定是否以及如何对每个状态做出反应。
我想在 BlocBuilder 中使用可选参数 buildWhen 是避免为每个事件创建新区块的最佳方式。
各位。我是 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 中。正是在那里,我遇到了对架构扩展的误解。此操作不应该 return 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),它不应该 return 我之前在同一个 bloc 捕获的状态,那么我需要为此目的创建新的 bloc 并且通过 multiProvider 覆盖我的屏幕?
您还应该 post 您的 ContactState 代码。
但是您不一定需要一个新的 Bloc。这完全取决于您要实现的目标。
我想当你 yield PhotoLoading()
你想展示一个装载机时。
但是当你更新照片时,如果我理解你想要实现的目标,你应该再次使用 yield ContactsLoaded(contacts)
或 add(GetContacts())
而不是 yield PhotoLoaded(photo: photo)
来生成更新的联系人列表。
如果你想显示一条确认消息,你可以保持你的 PhotoLoaded 状态,但你需要构建你的 UI 考虑到 bloc 可能发出的不同状态。
请记住,在 BloC 架构中,事件可以连续屈服于多个状态,UI 决定是否以及如何对每个状态做出反应。
我想在 BlocBuilder 中使用可选参数 buildWhen 是避免为每个事件创建新区块的最佳方式。