事件管理 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 是避免为每个事件创建新区块的最佳方式。