service_bloc

Dart package for service layer implement with bloc architecture

Usage

Create your own base service bloc to reduce redundant code, for example:

  • User permission (bloc level)
enum UserPermissionLevel {
  invalid,
  normal,
  vip,
}

class UserPermissionLevelCubit extends Cubit<UserPermissionLevel> {
  UserPermissionLevelCubit(UserPermissionLevel initialState)
      : super(UserPermissionLevel.invalid);
}

abstract class UserPermissionRequiredServiceBloc<
ServiceRequestedEvent extends ServiceRequested,
ResponseData> extends ServiceBloc<ServiceRequestedEvent, ResponseData> {
  UserPermissionRequiredServiceBloc(
      {required this.userPermissionLevelCubit,
        EventTransformer<ServiceRequestedEvent>? eventTransformer})
      : super(eventTransformer: eventTransformer);

  final UserPermissionLevelCubit userPermissionLevelCubit;
}

class ProductCheckoutServiceRequested extends ServiceRequested {
  const ProductCheckoutServiceRequested(this.productIdList);

  final List<String> productIdList;

  @override
  List<Object?> get props => [productIdList];
}

class ProductCheckoutServiceBloc extends UserPermissionRequiredServiceBloc<
    ProductCheckoutServiceRequested, String> {
  ProductCheckoutServiceBloc({
    required UserPermissionLevelCubit userPermissionLevelCubit,
    required this.repository,
  }) : super(userPermissionLevelCubit: userPermissionLevelCubit);

  final ProductRepository repository;

  @override
  FutureOr<void> onRequest(
      ProductCheckoutServiceRequested event, Emitter<ServiceState> emit) async {
    if (userPermissionLevelCubit.state == UserPermissionLevel.invalid) {
      // TODO: implement permission error
    }
    // TODO: implement onRequest
  }
}
  • Locale (event level)
class LocaleRequiredServiceRequested extends ServiceRequested {
  const LocaleRequiredServiceRequested({required this.locale});
  
  final Locale locale;
  
  @override
  List<Object?> get props => [locale];
}
  
class ProductDetailServiceRequested extends LocaleRequiredServiceRequested {
  const ProductDetailServiceRequested({
    required this.productId,
    required Locale locale,
  }) : super(locale: locale);
  
  final String productId;
  
  @override
  List<Object?> get props => [
    locale,
    productId,
  ];
}
  
abstract class LocaleRequiredServiceBloc<
ServiceRequested extends LocaleRequiredServiceRequested,
ResponseData> extends ServiceBloc<ServiceRequested, ResponseData> {}
  
class ProductDetailServiceBloc extends LocaleRequiredServiceBloc<
    ProductDetailServiceRequested, ProductDetail> {
  ProductDetailServiceBloc(this.repository);

  final ProductRepository repository;
  
  @override
  FutureOr<void> onRequest(
      ProductDetailServiceRequested event, Emitter<ServiceState> emit) async {
    final locale = event.locale;
    // TODO: implement onRequest
  }
}

This two examples shows that you can create your own service bloc with extensibility feature.

Implement the pagination easily with built-in pagination service bloc

  • Open library author search
class OpenLibraryAuthorSearchServiceRequested
    extends PaginationServiceRequested {
  const OpenLibraryAuthorSearchServiceRequested(this.keyword);

  final String keyword;

  @override
  List<Object?> get props => [
        keyword,
      ];
}

class OpenLibraryAuthorSearchReloadServiceRequested
    extends OpenLibraryAuthorSearchServiceRequested with PaginationReload {
  OpenLibraryAuthorSearchReloadServiceRequested(super.keyword);
}

class OpenLibraryAuthorSearchServiceBloc extends PaginationServiceBloc<
    OpenLibraryAuthorSearchServiceRequested,
    List<OpenLibraryAuthorSearchResult>,
    num> {
  OpenLibraryAuthorSearchServiceBloc(this.repository)
      : super(
    pagination: NumberBasedPagination(
      onUpdateHasNextPage: (responseData) => responseData.isNotEmpty,
    ),
    paginationResponseData: PaginationListResponseData(),
  );

  final OpenLibraryRepository repository;

  @override
  FutureOr<List<OpenLibraryAuthorSearchResult>> onPaginationRequest(
      OpenLibraryAuthorSearchServiceRequested event, num page) async {
    // TODO: implement onRequest
  }
}

Live Template

Generating boilerplate for service bloc

You can generate service bloc boilerplate code easily by using live template, check out setup to create your own shortcut with the following code.

class $SERVICE_NAME$ServiceRequested extends ServiceRequested {
  const $SERVICE_NAME$ServiceRequested();
  
  @override
  List<Object?> get props => [];
}

class $SERVICE_NAME$ServiceBloc extends ServiceBloc<$SERVICE_NAME$ServiceRequested, $RETURN_TYPE$> {

  @override
  FutureOr<void> onRequest($SERVICE_NAME$ServiceRequested event, Emitter<ServiceState> emit) async {
    $END$// TODO: implement service call
  }
}

For more example detail, please check out example.

Maintainer

Jack Liu

Libraries

service_bloc