fbloc_event_gen 3.2.1 copy "fbloc_event_gen: ^3.2.1" to clipboard
fbloc_event_gen: ^3.2.1 copied to clipboard

Intended to replace @freezed BLOC. Generates STATE, EVENT AND BLOC from a SINGLE LINE OF STATE VARIABLE and can generate custom event classes from factory constructors.

🚀 Flutter Bloc Generator #

✨ NOW WITH VSCODE EXTENSION! ✨

Get the "Fbloc Event Gen" extension from Visual Studio Marketplace to supercharge your development workflow!

Too much Unwanted freezed Bloc code... ??

Generate All state, event and even bloc code from a SINGLE VARIABLE

Update State with without having to Rememeber all those events.. in a single context.Set.. Fn()

With all options to CUSTOMISE your bloc and event code with out hastle

Then This is the Package u will ever need...

A powerful code generation package that supercharges your Flutter Bloc implementation with zero boilerplate! Generate events, states, and utilities automatically.

state image Placeholder

calling event image place holder

event image place holder

📚 Table of Contents #

📦 Installation #

Add to your pubspec.yaml:

dependencies:
  fbloc_event_gen: ^3.1.5

dev_dependencies:
  build_runner: ^2.4.6

Run:

flutter pub get

✨ Features #

  • 🎯 Two Powerful Annotations
    • @GenerateEvents - Generate events from factory constructors
    • @GenerateStates - Generate complete state management code
  • 🔄 Automatic Generation
    • Type-safe events and states
    • BuildContext extensions
    • Immutable state updates
  • 🛡️ Built-in Safety
    • Null safety support
    • Equatable implementation
    • Type checking

🎯 Usage #

@GenerateEvents #

Use @GenerateEvents when you need event-only generation. Perfect for defining bloc events through factory constructors.

import 'package:flutter_bloc_generator/annotations.dart';

@GenerateEvents
abstract class BaseEvent extends Equatable {
  const BaseEvent();
  
  // Factory constructors define your events
  factory BaseEvent.userLoggedIn({
    required String userId,
    required String token,
    bool? rememberMe,
  });
  
  factory BaseEvent.updateProfile({
    required UserModel user,
  });
  
  factory BaseEvent.logOut();
}

Generated Code ✨

// Generated events.g.dart

class UserLoggedIn extends BaseEvent {
  final String userId;
  final String token;
  final bool? rememberMe;

  const UserLoggedIn({
    required this.userId,
    required this.token,
    this.rememberMe,
  });

  @override
  List<Object?> get props => [userId, token, rememberMe];
}

class UpdateProfile extends BaseEvent {
  final UserModel user;

  const UpdateProfile({required this.user});

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

class LogOut extends BaseEvent {
  const LogOut();

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

@GenerateStates #

Use @GenerateStates for complete state management generation. Define your state variables in an abstract class.

import 'package:flutter_bloc_generator/annotations.dart';

@GenerateStates
abstract class _$$BaseState {
  final bool isAuthenticated = false;
  final bool isLoading = false;
  final UserModel? currentUser = null;
  final List<String> errorMessages = [];
  final AuthStatus authStatus = AuthStatus.initial;
  final Map<String, dynamic> userData = {};
}

Generated Code ✨

// Generated state.g.dart

/// 1️⃣ State Class Definition
class BaseState extends Equatable {
  final bool isAuthenticated;
  final bool isLoading;
  final UserModel? currentUser;
  final List<String> errorMessages;
  final AuthStatus authStatus;
  final Map<String, dynamic> userData;

  const BaseState({
    required this.isAuthenticated,
    required this.isLoading,
    this.currentUser,
    required this.errorMessages,
    required this.authStatus,
    required this.userData,
  });

  /// 2️⃣ State Mutation Utilities
  BaseState copyWith({
    /// Data type [bool]
    Object? isAuthenticated = UnspecifiedDataType.instance,
    /// Data type [bool] 
    Object? isLoading = UnspecifiedDataType.instance,
    /// Data type [UserModel?]
    Object? currentUser = UnspecifiedDataType.instance,
    /// Data type [List<String>]
    Object? errorMessages = UnspecifiedDataType.instance,
    /// Data type [AuthStatus]
    Object? authStatus = UnspecifiedDataType.instance,
    /// Data type [Map<String, dynamic>]
    Object? userData = UnspecifiedDataType.instance,
  }) {
    return BaseState(
      isAuthenticated: isAuthenticated is UnspecifiedDataType ? this.isAuthenticated : (isAuthenticated as bool),
      isLoading: isLoading is UnspecifiedDataType ? this.isLoading : (isLoading as bool),
      currentUser: currentUser is UnspecifiedDataType ? this.currentUser : (currentUser as UserModel?),
      errorMessages: errorMessages is UnspecifiedDataType ? this.errorMessages : (errorMessages as List<String>),
      authStatus: authStatus is UnspecifiedDataType ? this.authStatus : (authStatus as AuthStatus),
      userData: userData is UnspecifiedDataType ? this.userData : (userData as Map<String, dynamic>),
    );
  }

  /// 3️⃣ Initial State Factory
  static BaseState initial() {
    return BaseState(
      isAuthenticated: false,
      isLoading: false,
      currentUser: null,
      errorMessages: [],
      authStatus: AuthStatus.initial,
      userData: {},
    );
  }

  /// 4️⃣ State Update Events
  class UpdateIsAuthenticatedEvent extends BaseEvent {
    final bool isAuthenticated;
    const UpdateIsAuthenticatedEvent({required this.isAuthenticated});
    @override
    List<Object?> get props => [isAuthenticated];
  }
  // ... events for each state variable

  /// 5️⃣ Event Handlers Registration
  static void registerEvents(BaseBloc bloc) {
    bloc.on<UpdateIsAuthenticatedEvent>((event, emit) {
      emit(bloc.state.copyWith(isAuthenticated: event.isAuthenticated));
    });
    bloc.on<UpdateIsLoadingEvent>((event, emit) {
      emit(bloc.state.copyWith(isLoading: event.isLoading));
    });
    // ... handlers for all events
  }

  /// 6️⃣ Equatable Implementation
  @override
  List<Object?> get props => [
    isAuthenticated,
    isLoading,
    currentUser,
    errorMessages,
    authStatus,
    userData,
  ];
}

/// 7️⃣ BuildContext Extensions
extension BaseBlocContextExtension on BuildContext {
  void setBaseBlocState({
    Object? isAuthenticated = UnspecifiedDataType.instance,
    Object? isLoading = UnspecifiedDataType.instance,
    Object? currentUser = UnspecifiedDataType.instance,
    Object? errorMessages = UnspecifiedDataType.instance,
    Object? authStatus = UnspecifiedDataType.instance,
    Object? userData = UnspecifiedDataType.instance,
  }) {
    final bloc = read<BaseBloc>();
    if (isAuthenticated != UnspecifiedDataType.instance) {
      bloc.add(UpdateIsAuthenticatedEvent(isAuthenticated: isAuthenticated as bool));
    }
    if (isLoading != UnspecifiedDataType.instance) {
      bloc.add(UpdateIsLoadingEvent(isLoading: isLoading as bool));
    }
    // ... handlers for all state updates
  }
}

🛠️ Implementation #

Bloc Class #

class BaseBloc extends Bloc<BaseEvent, BaseState> {
  BaseBloc() : super(BaseState.initial()) {
    // Register all event handlers automatically
    BaseState.registerEvents(this);
    
    // Add your custom event handlers
    on<UserLoggedIn>(_onUserLoggedIn);
  }

  Future<void> _onUserLoggedIn(
    UserLoggedIn event,
    Emitter<BaseState> emit,
  ) async {
    emit(state.copyWith(isLoading: true));
    // ... authentication logic
    emit(state.copyWith(
      isLoading: false,
      isAuthenticated: true,
    ));
  }
}

Widget Usage #

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Traditional way
    context.read<BaseBloc>().add(
      UpdateProfile(user: updatedUser)
    );

    // Using generated extension (Cleaner!)
    context.setBaseBlocState(
      isLoading: true,
      currentUser: updatedUser,
      authStatus: AuthStatus.authenticated,
    );
  }
}

🎯 Best Practices #

  1. State Variables

    • Keep state classes focused and minimal
    • Use meaningful variable names
    • Consider nullability carefully
  2. Event Generation

    • Use descriptive factory constructor names
    • Group related events together
    • Document complex event parameters
  3. State Updates

    • Prefer extension methods for simple updates
    • Use traditional events for complex logic
    • Keep state immutable

🔄 Migration Guide #

2.0.0 to 3.0.0 #

  • Update annotation imports
  • Rename existing state classes to include _$$ prefix
  • Add initial values to state variables
  • Run code generation

🤝 Contributing #

We welcome contributions! Please see our contributing guide for details.

📝 License #

This project is licensed under the MIT License - see the LICENSE file for details.

3
likes
160
points
501
downloads
screenshot

Publisher

unverified uploader

Weekly Downloads

Intended to replace @freezed BLOC. Generates STATE, EVENT AND BLOC from a SINGLE LINE OF STATE VARIABLE and can generate custom event classes from factory constructors.

Repository (GitHub)
View/report issues

Topics

#bloc-generator #bloc-event-generator #bloc-state-generator #freezed #build-runner-generator

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, build, build_runner, equatable, source_gen

More

Packages that depend on fbloc_event_gen