bloc_subject 0.4.1 copy "bloc_subject: ^0.4.1" to clipboard
bloc_subject: ^0.4.1 copied to clipboard

Reactive event based state management. Implementation of the Bloc pattern as an rxdart subject (BlocSubject).

Pub Version Dart Package Docs License: Apache 2.0 Build Status

bloc_subject #

bloc_subject is a Dart package that introduces the BlocSubject class, an extension of RxDart's BehaviorSubject with the powerful BLoC (Business Logic Component) pattern. It allows you to handle events and state changes in a reactive way, leveraging RxDart's stream manipulation capabilities while maintaining state and responding to events asynchronously.

sealed class AlphabetState {
  final int id;

  AlphabetState(this.id);
}

class A extends AlphabetState {
  A(super.id);
}

class B extends AlphabetState {
  B(super.id);
}

class C extends AlphabetState {
  C(super.id);
}

sealed class AlphabetEvent {}

class X implements AlphabetEvent {}

class Y implements AlphabetEvent {}

class Z implements AlphabetEvent {}

void main() async {
  int emitCount = 0;
  BlocSubject<AlphabetEvent, AlphabetState> subject = BlocSubject.seeded(A(emitCount),
      handler: (event, state) => switch (event) {
            X() => A(++emitCount),
            Y() => B(++emitCount),
            Z() => null,
          });
  final transformedStream = subject.stream
      .map((value) => switch (value) {
            A() => "A${value.id}",
            B() => "B${value.id}",
            C() => "C${value.id}",
          })
      .distinct();

  assert(subject.value is A);
  assert(await transformedStream.first == "A0");

  subject.addEvent(Y()); // Can process events and emit new states
  await Future.delayed(const Duration(milliseconds: 100));
  assert(subject.value is B);
  assert(await transformedStream.first == "B1");

  subject.addEvent(Z()); // If null is emitted from the handler, the state does not change/emit
  await Future.delayed(const Duration(milliseconds: 100));
  assert(subject.value is B);
  assert(await transformedStream.first == "B1");

  subject.add(C(1000)); // Still works like a regular `BehaviorSubject`
  assert(subject.value is C);
  assert(await transformedStream.first == "C1000");
}

Declaration Comparison To Bloc #

Bloc:

import 'package:bloc/bloc.dart';

void main(){
    final bloc = HomeBloc();
}

class HomeBloc extends Bloc<HomeEvent, HomeState> {

  final DocumentInfoRepository _documentInfoRepository = DI<DocumentInfoRepository>();
  late final StreamSubscription<(DocumentChange<Map<String, dynamic>>, DocumentInfo)>
      _documentInfoChangesStreamSubscription;

  HomeBloc() : super(HomeState()) {
    on<HomeEventAddedDocumentInfo>(_handleAddedDocumentInfo);
    on<HomeEventModifiedDocumentInfo>(_handleModifiedDocumentInfo);
    on<HomeEventRemovedDocumentInfo>(_handleRemovedDocumentInfo);
    on<HomeEventChangeCurrentDirectory>(_handleChangeCurrentDirectory);
    on<HomeEventSortOptionsChanged>(_handleSortOptionsChanged);
    on<HomeEventMoveSelected>(_handleMoveSelectedTo);
    on<HomeEventCreateFolder>(_handleCreateFolderAt);

    _documentInfoChangesStreamSubscription =
        _documentInfoRepository.userDocumentInfoChangeStream().listen((item) {
      final (event, doc) = item;
      switch (event.type) {
        case DocumentChangeType.added:
          add(HomeEventAddedDocumentInfo(doc));
          break;
        case DocumentChangeType.modified:
          add(HomeEventModifiedDocumentInfo(doc));
          break;
        case DocumentChangeType.removed:
          add(HomeEventRemovedDocumentInfo(doc));
          break;
      }
    });
  }

  @override
  Future<void> close() async {
    await _documentInfoChangesStreamSubscription.cancel();
    return super.close();
  }

  Future<void> _handleAddedDocumentInfo(HomeEventAddedDocumentInfo event, Emitter<HomeState> emit) async {
    ...
  }

  Future<void> _handleModifiedDocumentInfo(HomeEventModifiedDocumentInfo event, Emitter<HomeState> emit) async {
    ...
  }

  Future<void> _handleRemovedDocumentInfo(HomeEventRemovedDocumentInfo event, Emitter<HomeState> emit) async {
    ...
  }

  void _handleChangeCurrentDirectory(HomeEventChangeCurrentDirectory event, Emitter<HomeState> emit) {
    ...
  }

  void _handleSortOptionsChanged(HomeEventSortOptionsChanged event, Emitter<HomeState> emit) {
    ...
  }

  void _handleMoveSelectedTo(HomeEventMoveSelected event, Emitter<HomeState> emit) {
    ...
  }

  void _handleCreateFolderAt(HomeEventCreateFolder event, Emitter<HomeState> emit) {
    ...
  }
}

bloc_subject:

import 'package:bloc_subject/bloc_subject.dart';

void main() {
    final blocSubject = BlocSubject<HomeEvent, HomeState>.seeded(
        HomeState(),
        handler: (event, state) => switch (event) {
            HomeEventAddedDocumentInfo() => _handleAddedDocumentInfo(event, state),
            HomeEventModifiedDocumentInfo() => _handleModifiedDocumentInfo(event, state),
            HomeEventRemovedDocumentInfo() => _handleRemovedDocumentInfo(event, state),
            HomeEventChangeCurrentDirectory() => _handleChangeCurrentDirectory(event, state),
            HomeEventSortOptionsChanged() => _handleSortOptionsChanged(event, state),
            HomeEventMoveSelected() => _handleMoveSelectedTo(event, state),
            HomeEventCreateFolder() => _handleCreateFolderAt(event, state),
        },
        )..listenToEvents(DI<DocumentInfoRepository>().userDocumentInfoChangeStream().map((item) {
            final (event, doc) = item;
            return switch (event.type) {
                DocumentChangeType.added => HomeEventAddedDocumentInfo(doc),
                DocumentChangeType.modified => HomeEventModifiedDocumentInfo(doc),
                DocumentChangeType.removed => HomeEventRemovedDocumentInfo(doc),
            };
        }));
}

HomeState? _handleAddedDocumentInfo(HomeEventAddedDocumentInfo event, HomeState state) {
    ...
}

HomeState? _handleModifiedDocumentInfo(HomeEventModifiedDocumentInfo event, HomeState state) {
    ...
}

HomeState? _handleRemovedDocumentInfo(HomeEventRemovedDocumentInfo event, HomeState state) {
    ...
}

HomeState? _handleChangeCurrentDirectory(HomeEventChangeCurrentDirectory event, HomeState state) {
    ...
}

HomeState? _handleSortOptionsChanged(HomeEventSortOptionsChanged event, HomeState state) {
    ...
}

HomeState? _handleMoveSelectedTo(HomeEventMoveSelected event, HomeState state) {
    ...
}

HomeState? _handleCreateFolderAt(HomeEventCreateFolder event, HomeState state) {
    ...
}
4
likes
160
points
51
downloads

Documentation

API reference

Publisher

verified publishervoyver.com

Weekly Downloads

Reactive event based state management. Implementation of the Bloc pattern as an rxdart subject (BlocSubject).

Repository (GitHub)
View/report issues

Topics

#bloc #rxdart #reactive-programming #streams #reactive

License

Apache-2.0 (license)

Dependencies

rxdart

More

Packages that depend on bloc_subject