A predictable state management library that helps implement the BLoC design pattern

Overview

Bloc

build codecov Star on Github style: effective dart Flutter Website Awesome Flutter Flutter Samples License: MIT Discord Bloc Library


A predictable state management library that helps implement the BLoC design pattern.

Package Pub
bloc pub package
bloc_test pub package
flutter_bloc pub package
angular_bloc pub package
hydrated_bloc pub package
replay_bloc pub package

Sponsors

Our top sponsors are shown below! [Become a Sponsor]


Try the Flutter Chat Tutorial   πŸ’¬

Overview

Bloc Architecture

The goal of this library is to make it easy to separate presentation from business logic, facilitating testability and reusability.

Documentation

Migration

Examples

Dart

  • Counter - an example of how to create a CounterBloc (pure dart).

Flutter

  • Counter - an example of how to create a CounterBloc to implement the classic Flutter Counter app.
  • Form Validation - an example of how to use the bloc and flutter_bloc packages to implement form validation.
  • Bloc with Stream - an example of how to hook up a bloc to a Stream and update the UI in response to data from the Stream.
  • Complex List - an example of how to manage a list of items and asynchronously delete items one at a time using bloc and flutter_bloc.
  • Infinite List - an example of how to use the bloc and flutter_bloc packages to implement an infinite scrolling list.
  • Login Flow - an example of how to use the bloc and flutter_bloc packages to implement a Login Flow.
  • Firebase Login - an example of how to use the bloc and flutter_bloc packages to implement login via Firebase.
  • Github Search - an example of how to create a Github Search Application using the bloc and flutter_bloc packages.
  • Weather - an example of how to create a Weather Application using the bloc and flutter_bloc packages. The app uses a RefreshIndicator to implement "pull-to-refresh" as well as dynamic theming.
  • Todos - an example of how to create a Todos Application using the bloc and flutter_bloc packages.
  • Timer - an example of how to create a Timer using the bloc and flutter_bloc packages.
  • Firestore Todos - an example of how to create a Todos Application using the bloc and flutter_bloc packages that integrates with cloud firestore.
  • Shopping Cart - an example of how to create a Shopping Cart Application using the bloc and flutter_bloc packages based on flutter samples.
  • Dynamic Form - an example of how to use the bloc and flutter_bloc packages to implement a dynamic form which pulls data from a repository.
  • Wizard - an example of how to build a multi-step wizard using the bloc and flutter_bloc packages.
  • GraphQL - an example of how to use the bloc and flutter_bloc packages with graphql to retrieve data from api.graphql.jobs.
  • Fluttersaurus - an example of how to use the bloc and flutter_bloc packages to create a thesaurus app -- made for Bytconf Flutter 2020.

Web

  • Counter - an example of how to use a CounterBloc in an AngularDart app.
  • Github Search - an example of how to create a Github Search Application using the bloc and angular_bloc packages.

Flutter + Web

  • Github Search - an example of how to create a Github Search Application and share code between Flutter and AngularDart.

Articles

Books

  • Flutter Complete Reference - A book about the Dart programming language (version 2.10, with null safety support) and the Flutter framework (version 1.20). It covers the bloc package (version 6.0.3) in all flavors: bloc, flutter_bloc hydrated_bloc, replay_bloc, bloc_test and cubit.

Extensions

  • IntelliJ - extends IntelliJ/Android Studio with support for the Bloc library and provides tools for effectively creating Blocs for both Flutter and AngularDart apps.
  • VSCode - extends VSCode with support for the Bloc library and provides tools for effectively creating Blocs for both Flutter and AngularDart apps.

Community

Learn more at the following links, which have been contributed by the community.

Packages

Video Tutorials

Written Resources

Extensions

Maintainers

Issues
  • [Proposal] Replace `mapEventToState` with `on<Event>` in `Bloc`

    [Proposal] Replace `mapEventToState` with `on` in `Bloc`

    Hello everyone! πŸ‘‹

    First of all, I want to thank everyone for the amazing support and community that has grown around the bloc library! πŸ™πŸ’™

    Context

    This proposal aims to address 3 problems with the current mapEventToState implementation:

    1. Predictability
    2. Learning Curve and Complexity
    3. Boilerplate

    Predictability

    Due to an issue in Dart, it is not always intuitive what the value of state will be when dealing with nested async generators which emit multiple states. Even though there are ways to work around this issue, one of the core principles/goals of the bloc library is to be predictable. Therefore, the primary motivation of this proposal is to make the library as safe as possible to use and eliminate any uncertainty when it comes to the order and value of state changes.

    Learning Curve and Complexity

    Writing blocs requires an understanding of Streams and async generators. This means developers must understand how to use the async*, yield, and yield* keywords. While these concepts are covered in the documentation, they are still fairly complex and difficult for newcomers to grasp.

    Boilerplate

    When writing a bloc, developers must override mapEventToState and then handle the incoming event(s). Often times this looks something like:

    @override
    Stream<State> mapEventToState(Event event) async* {
      if (event is EventA) {
        yield* _mapEventAToState(event);
      } else if (event is EventB) {
        yield* _mapEventBToState(event);
      }
    }
    
    Stream<State> _mapEventAToState(EventA event) async* {...}
    Stream<State> _mapEventBToState(EventB event) async* {...}
    

    The important logic usually lives inside _mapEventAToState and _mapEventBToState and mapEventToState ends up mainly being setup code to handle determining which mapper to call based on the event type. It would be nice if this could be streamlined.

    Proposal πŸ₯

    I am proposing to remove the mapEventToState API in favor of on<Event>. This would allow developers to register event handlers by calling on<Event> where Event is the type of event being handled. on<Event> would provide a callback (Event event, Emitter<State>) {...} which would be invoked when an event of type Event is added to the bloc. Developers could then emit one or more states in response to the incoming event.

    For example, if we look at the CounterBloc for reference, the current implementation might look something like:

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0);
    
      @override
      Stream<int> mapEventToState(CounterEvent event) async* {
        if (event is Increment) {
          yield state + 1;
        }
      }
    }
    

    With the proposed changes the CounterBloc would look something like:

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0) {
        on<Increment>((event, emit) => emit(state + 1));
      }
    }
    

    If we wanted to support multiple events:

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    class Decrement extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0) {
        on<Increment>((event, emit) => emit(state + 1));
        on<Decrement>((event, emit) => emit(state - 1));
      }
    }
    

    For more complex logic it can be refactored to look like:

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    class Decrement extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0) {
        on<Increment>(_onIncrement);
        on<Decrement>(_onDecrement);
      }
    
      void _onIncrement(Increment event, Emitter<int> emit) {
        emit(state + 1);
      }
    
      void _onDecrement(Decrement event, Emitter<int> emit) {
        emit(state - 1);
      }
    }
    

    These changes address the predictability issues mentioned above because it can be guaranteed that the bloc's state will update immediately when emit is called ensuring that cases like this behave as expected:

      void _onIncrement(Increment event, Emitter<int> emit) {
        emit(state + 1); // state starts off at 0 so we emit 1
        emit(state + 1); // state is 1 now so we emit 2
      }
    

    In addition, developers don't have to use async generators (async*, yield, yield*) which can introduce complexity and undesired behavior in advanced cases.

    This allows developers to focus on the logic by directly registering an event handler for each type of event which streamlines the bloc code a bit further.

    An added benefit is the added consistency across Cubit and Bloc -- both trigger state changes via emit and the transition from Cubit to Bloc should become simpler.

    class CounterCubit extends Cubit<int> {
      CounterCubit() : super(0);
    
      void increment() => emit(state + 1);
    }
    

    Becomes

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0) {
        on<Increment>(_onIncrement);
      }
    
      void _onIncrement(Increment event, Emitter<int> emit) {
        emit(state + 1);
      }
    }
    

    Or as mentioned above (for simple cases)

    abstract class CounterEvent {}
    class Increment extends CounterEvent {}
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      CounterBloc() : super(0) {
        on<Increment>((event, emit) => emit(state + 1));
      }
    }
    

    These changes will obviously be breaking changes that impact blocs (cubits will remain unaffected) so they would all be within the scope of a v8.0.0 release.

    The changes would be made in a way that only impacts the bloc mapEventToState implementation. The way blocs are used and tested will be 100% backward compatible which means the changes will be scoped to just the mapEventToState code and can ideally be automated via a code mod. There should be no impact to the remaining ecosystem (flutter_bloc, bloc_test, hydrated_bloc, replay_bloc, etc...).

    Please give this issue a πŸ‘ if you support the proposal or a πŸ‘Ž if you're against it. If you disagree with the proposal I would really appreciate it if you could comment with your reasoning.

    Thanks so much for all of the continued support and looking forward to hearing everyone's thoughts on the proposal! πŸ™


    08/31 UPDATE

    Hey everyone, just wanted to give a quick update:

    We currently have the v8.0.0 branch which replaces mapEventToState with on<Event>; however, we were able to make on<Event> backward compatible with mapEventToState πŸŽ‰ . You can view the changes as part of the v7.2.0 branch.

    The current plan is to roll out bloc v7.2.0 in the coming days which will deprecate mapEventToState, transformEvents, and transformTransitions and will introduce the new on<Event> API. We will have a comprehensive migration guide explaining all of the changes and how to migrate over. During this time, we encourage everyone to upgrade to bloc v7.2.0 and start to migrate blocs one at a time. In the meantime, we'll be working on development releases of bloc v8.0.0.

    As part of v8.0.0 all deprecated APIs from v7.2.0 will be removed and the tentative plan is to publish a stable v8.0.0 release about a month after v7.2.0 has been release. This should give everyone some time to incrementally migrate and for any adjustments to be made. In addition, v7.x.x will still receive bug fixes for the foreseeable future so there should be no pressure/urgency to jump to v8.0.0.

    Let us know if you have any questions/concerns.

    Thanks for everyone's feedback, patience, and continued support! πŸ’™ πŸ™

    09/02 UPDATE

    We just published bloc v7.2.0-dev.1 which introduces the on<Event> API and is backwards compatible which should allow you to migrate incrementally. πŸŽ‰ ✨

    bloc-v7 2 0

    Release Notes: https://github.com/felangel/bloc/releases/tag/bloc-v7.2.0-dev.1

    Please try it out and let us know if you have any feedback/questions, thanks! πŸ™ πŸ’™

    09/09 UPDATE

    We just published bloc v7.2.0-dev.2 πŸŽ‰ Release Notes: https://github.com/felangel/bloc/releases/tag/bloc-v7.2.0-dev.2

    09/10 UPDATE

    We just published bloc v7.2.0-dev.3 πŸŽ‰ Release Notes: https://github.com/felangel/bloc/releases/tag/bloc-v7.2.0-dev.3

    09/21 UPDATE

    The time has come πŸ₯ πŸ₯ πŸ₯

    bloc v7.2.0 is now out πŸŽ‰

    πŸ“¦ update now: https://pub.dev/packages/bloc/versions/7.2.0 πŸ“” migration guide: https://bloclibrary.dev/#/migration?id=v720

    enhancement candidate discussion feedback wanted pkg:bloc 
    opened by felangel 125
  • Bad state: Cannot add new events after calling close

    Bad state: Cannot add new events after calling close

    I can't trace the issue on my code, not sure it's my code problem or the library

    StateError: Bad state: Cannot add new events after calling close
      File "broadcast_stream_controller.dart", line 253, in _BroadcastStreamController.add
      File "subject.dart", line 124, in Subject._add
      File "subject.dart", line 118, in Subject.add
      File "bloc.dart", line 73, in Bloc._bindStateSubject.<fn>
      File "stream.dart", line 816, in Stream.forEach.<fn>.<fn>
      File "stream_pipe.dart", line 11, in _runUserCode
      File "stream.dart", line 816, in Stream.forEach.<fn>
      File "zone.dart", line 1132, in _rootRunUnary
      File "zone.dart", line 1029, in _CustomZone.runUnary
      File "zone.dart", line 931, in _CustomZone.runUnaryGuarded
      File "stream_impl.dart", line 336, in _BufferingStreamSubscription._sendData
      File "stream_impl.dart", line 263, in _BufferingStreamSubscription._add
      File "broadcast_stream_controller.dart", line 379, in _SyncBroadcastStreamController._sendData
      File "broadcast_stream_controller.dart", line 291, in _BroadcastStreamController._add
      File "zone.dart", line 1132, in _rootRunUnary
      File "zone.dart", line 1029, in _CustomZone.runUnary
      File "zone.dart", line 931, in _CustomZone.runUnaryGuarded
      File "stream_impl.dart", line 336, in _BufferingStreamSubscription._sendData
      File "stream_impl.dart", line 591, in _DelayedData.perform
      File "stream_impl.dart", line 707, in _StreamImplEvents.handleNext
      File "stream_impl.dart", line 667, in _PendingEvents.schedule.<fn>
      File "zone.dart", line 1120, in _rootRun
      File "zone.dart", line 1021, in _CustomZone.run
      File "zone.dart", line 923, in _CustomZone.runGuarded
      File "zone.dart", line 963, in _CustomZone.bindCallbackGuarded.<fn>
      File "zone.dart", line 1124, in _rootRun
      File "zone.dart", line 1021, in _CustomZone.run
      File "zone.dart", line 923, in _CustomZone.runGuarded
      File "zone.dart", line 963, in _CustomZone.bindCallbackGuarded.<fn>
      File "schedule_microtask.dart", line 41, in _microtaskLoop
      File "schedule_microtask.dart", line 50, in _startMicrotaskLoop
    
    question 
    opened by anderscheow 75
  • [Feature Request] MultiBlocBuilder

    [Feature Request] MultiBlocBuilder

    Sometimes I would need to access different blocs in the same widget, and the code goes pretty messy. I am thinking maybe we can have something like MultiBlocBuilder which serve the similar purpose of MultiRepositoryProvider and MultiBlocProvider.

    enhancement candidate discussion feedback wanted 
    opened by PhilipChng 69
  • [Discussion] Improve Bloc to Bloc/Stream Integration

    [Discussion] Improve Bloc to Bloc/Stream Integration

    Is your feature request related to a problem? Please describe. When using bloc, it is fairly common to have blocs which need to react to other blocs or Streams. The current recommended approach involves directly subscribing to the Stream within the bloc:

    class MyBloc extends Bloc {
      final OtherBloc otherBloc;
      StreamSubscription otherBlocSubscription;
    
      MyBloc(this.otherBloc) {
        otherBlocSubscription = otherBloc.listen((state) {
            // React to state changes here.
            // Add events here to trigger changes in MyBloc.
        });
      }
    
      @override
      Future<void> close() {
        otherBlocSubscription.cancel();
        return super.close();
      }
    }
    

    This is not ideal because it requires one or more subscriptions to be managed manually and introduces additional complexity which increases with the number of consumed Streams.

    Describe the solution you'd like

    UPDATED PROPOSAL: https://github.com/felangel/bloc/issues/765#issuecomment-573368016

    ~~It might be better to potentially introduce a new widget -- something like BlocSink which handles the subscription to the desired Stream and exposes callbacks which allow developers to conveniently add an event to the desired bloc.~~

    BlocSink<int, TickerBloc, TickerEvent>( // stream data type, bloc type, event type
      stream: Stream.periodic(Duration(seconds: 1), (x) => x).take(10),
      bloc: BlocProvider.of<TickerBloc>(context), // optional - will look up bloc via context by default
      onData: (tick, add) => add(Tick(tick)),
      onError: (error, add) => add(TickError(error)), // optional
      onDone: (add) => add(TickFinished()), // optional
      child: MyChild(),
    )
    

    ~~In the above example, BlocSink would subscribe to the Stream.periodic and each time data is emitted, it would add a Tick event to the TickerBloc with the current tick. If an error is emitted, it would add a TickError with the current error and once the Stream has completed, it will add a TickFinished event.~~

    enhancement candidate discussion feedback wanted pkg:bloc 
    opened by felangel 52
  • Doc request: How to use bloc across pages?

    Doc request: How to use bloc across pages?

    Let's extended counter example, where all is working well.

    Imagine I add a thir fab action that uses navigator.pushReplacement to navigate a different page.

    The destination page needs to see counter value.

    How to?

    question 
    opened by realtebo 51
  • [Proposal?] 'Stream<State> get state' is confusing

    [Proposal?] 'Stream get state' is confusing

    I've been developing a relatively large app using Bloc and I think my top 1 issue with Bloc is with state. No, not what you are thinking. I mean, the state variable/getter method. image

    It has happened to me once, then again, then again, then today. I always cast it, like (currentState as ContrastLoadedState) and I keep trying state before realising my mistake. Just check the screenshot above. It makes no sense for me that currentState returns a State while state returns a Stream<State>.

    In BlocBuilder you get a state: https://github.com/felangel/bloc/blob/805cf865fe0972e7f1bd24f08598d624066434fb/examples/flutter_shopping_cart/lib/catalog/my_catalog.dart#L52

    In your own sample you use state = currentState: https://github.com/felangel/bloc/blob/805cf865fe0972e7f1bd24f08598d624066434fb/examples/flutter_shopping_cart/lib/cart/bloc/cart_bloc.dart#L31

    I think you could change state to stateStream and currentState to state or maybe just rename state to stateStream, that way there wouldn't be a state and IntelliJ/VSCode would be smart enough to just suggest currentState.

    I'm not sure if this has been a source of bugs/confusion in the past, but it has been a great frustration for me.

    enhancement deprecation 
    opened by bernaferrari 43
  • How to dispatch an event many times

    How to dispatch an event many times

    Hi there, first of all let me thank you for the awesome libraby. I face a problem with my block. I cannot send an event multiple times. It seems that mapEventToState is an asynchronous function, so currently can be equal to the state, so the data cannot be returned. You can give me a solution. Thanks very much. Sorry, my english is bad.

    question 
    opened by hahai96 40
  • flutter bloc about use multiple states at the same time

    flutter bloc about use multiple states at the same time

    can blocBuillder receive multiple states like (context, state:[stateA, stateB]) from different bloc?

    question 
    opened by windinvip 39
  • Migrate to bloc v7.2.0 question and log issue

    Migrate to bloc v7.2.0 question and log issue

    Hi @felangel first of all, thank you for providing such a great package for managing state in Flutter. I like it a lot! I have two questions. First, Since I am trying to migrate my bloc to bloc v7.2.0. I am not sure if this is the correct way. Since I am using Freezed to generate state and event. Here are my old and new migrated codes.

    Event:

    
    @freezed
    class ImagesEvent with _$ImagesEvent {
      const factory ImagesEvent.imagesFetched() =
          _ImagesFetched;
      const factory ImagesEvent.imagesFetchedNextPage() =
          _ImagesFetchedNextPage;
    }
    
    

    State:

    
    @freezed
    class ImagesState with _$ImagesState {
      const factory ImagesState.initial() = _Initial;
      const factory ImagesState.isLoading() = _IsLoading;
      const factory ImagesState.success() = _Success;
      const factory ImagesState.failure() = _Failure;
    }
    
    

    Old Bloc:

    
    @override
      Stream<ImagesState> mapEventToState(
        ImagesEvent event,
      ) async* {
        yield* event.map(
          imagesFetched: (e) async* {
            yield ImagesState.isLoading(
              );
    
            final failureOrSuccess =
                await repository.getImages();
    
            yield failureOrSuccess.fold(
              (l) => ImagesState.failure(),
              (r) => ImagesState.success(),
            );
          },
          imagesFetchedNextPage: (e) async* {
            yield ImagesState.isLoading(
              );
    
            final failureOrSuccess =
                await repository.getImages();
    
            yield failureOrSuccess.fold(
              (l) => ImagesState.failure(),
              (r) => ImagesState.success(),
            );
          },
        );
      }
    
    

    Migrated Bloc:

    class ImagesBloc
        extends Bloc<ImagesEvent, ImagesState> {
    
      ImagesBloc()
          : super(_Initial()) {
        on<ImagesEvent>((event, emit) async {
          await event.map(
            imagesFetched: (_) async {
    
                emit( ImagesState.isLoading());
    
                final failureOrSuccess =
                    await repository.getImages();
    
                emit(
                  failureOrSuccess.fold(
                    (l) => ImagesState.failure(),
                    (r) => ImagesState.success(),
                  ),
                );
            },
            imagesFetchedNextPage: (_) async {
    
                emit(ImagesState.isLoading());
    
                final failureOrSuccess =
                    await repository.getImages();
    
                emit(
                  failureOrSuccess.fold(
                    (l) => ImagesState.failure(),
                    (r) => ImagesState.success(),
                  ),
                );
            });
        });
      }
    }
    
    

    Second is, initially when I am not providing async after on<ImagesEvent> and before event.map() like below. I get an error log from runZonedGuarded (also below). It seems to have a /n new line error. The new line is not showing correctly. The upper part (blue text) is the error message that I manually print out.

    Another is I already add the async in front of imagesFetched: (_) async {} do I have to add async to the on<ImagesEvent> and event.map() ?

    
        on<ImagesEvent>((event, emit) /*async*/ {
          /*async*/ event.map(
            imagesFetched: (_) async {
    
                emit( ImagesState.isLoading());
    
                final failureOrSuccess =
                    await repository.getImages();
    
                emit(
                  failureOrSuccess.fold(
                    (l) => ImagesState.failure(),
                    (r) => ImagesState.success(),
                  ),
                );
            },
            //....
    }
    

    Error Message: bloc_issue

    Thanks a lot!

    question 
    opened by AscentionOne 36
  • How to show/hide Dialog when state changed?

    How to show/hide Dialog when state changed?

    Hello I want to know how to show/hide Dialog when state changed. For example in a bloc that have state isLoading i want to show a Dialog, and when the state isNotLoading i want to hide this.

    But I read for hide dialog i need to use Navigator.pop(), so when I used that the Navigator pop the screen

    I am trying with something like this:

    bloc.state.listen(
      (state) {
        if(state.isLoading){
          showDialog(
            // ...
          )        
        }else{
          // Here I want to hide the dialog
          // This Pop the current page :(
         Navigator.of(context).pop() 
        }
      }
    }
    

    Also, I implement using a Container with Stack, but If I put in the body of Scafold, the Container with the loading widget not overlap the AppBar. so for overlap the AppBar i need to put this in a Column in the body of the Scaffold.

    I don't like this form, so i want to find how to use showDialog or maybe other solution.

    thanks,

    question 
    opened by basketball-ico 36
  • [Question] Getting comparison issue while testing with Equatable (bloc_test)

    [Question] Getting comparison issue while testing with Equatable (bloc_test)

    todos_state.dart

    part of 'todos_bloc.dart';
    
    abstract class TodosState extends Equatable {
      const TodosState();
    
      @override
      List<Object> get props => [];
    }
    
    class TodoLoadInProgress extends TodosState {}
    
    class TodoLoadSuccess extends TodosState {
      final List<Todo> todos;
    
      TodoLoadSuccess([this.todos = const []]);
    
      @override
      List<Object> get props => [todos];
    
      @override
      String toString() => 'TodosLoadSuccess { todos: $todos }';
    }
    
    class TodosLoadFailure extends TodosState {}
    
    class TodosExceptionState extends TodosState {
      final List<dynamic> message;
    
      TodosExceptionState(this.message);
    
      @override
      List<Object> get props => [message];
    }
    

    todo_bloc_test.dart

    class MockTodoRepository extends Mock implements TodoRepository {}
    
    class MockErrorHandlerRepository extends Mock
        implements ErrorHandlerRepository {}
    
    void main() {
      late MockTodoRepository _todoRepository;
      late MockErrorHandlerRepository _errorHandlerRepository;
      late TodosBloc todosBloc;
    
      setUpAll(() {
        _todoRepository = MockTodoRepository();
        _errorHandlerRepository = MockErrorHandlerRepository();
        todosBloc = TodosBloc(_todoRepository, _errorHandlerRepository);
      });
      group("TodoBloc", () {
        test("initial state is TodoLoadInProgress", () {
          expect(todosBloc.state, TodoLoadInProgress());
        });
    
       // Failed on this test
        blocTest<TodosBloc, TodosState>(
          "emits [TodoLoadSuccess] on load",
          build: () => todosBloc,
          setUp: () {
            when(() => _todoRepository.getTodo())
                .thenAnswer((_) async => fakeTodoResponse);
          },
          act: (bloc) => bloc.add(TodosLoadedEvent()),
          expect: () => [
            TodoLoadSuccess(fakeTodoResponse),
          ],
        );
      });
    }
    

    fake_response.dart

    List<Todo> fakeTodoResponse = [
      Todo(
        id: 50,
        title: "updated title 3",
        description: "updated description",
        createdDate: "2021-05-07T14:47:54.247Z",
      ),
      Todo(
        id: 59,
        title: "new elastic updated title",
        description: "new elastic description",
        createdDate: "2021-05-10T05:48:32.893Z",
      ),
      Todo(
        id: 57,
        title: "elastic one update v4",
        description: "elastic description one update v4",
        createdDate: "2021-05-10T03:10:01.160Z",
      ),
    ];
    

    The error message -

    Expected: [
                TodoLoadSuccess:TodosLoadSuccess { todos: [Instance of 'Todo', Instance of 'Todo', Instance of 'Todo'] }
              ]
      Actual: [
                TodoLoadSuccess:TodosLoadSuccess { todos: [Instance of 'Todo', Instance of 'Todo', Instance of 'Todo'] }
              ]
       Which: at location [0] is TodoLoadSuccess:<TodosLoadSuccess { todos: [Instance of 'Todo', Instance of 'Todo', Instance of 'Todo'] }> instead of TodoLoadSuccess:<TodosLoadSuccess { todos: [Instance of 'Todo', Instance of 'Todo', Instance of 'Todo'] }>
    
    WARNING: Please ensure state instances extend Equatable, override == and hashCode, or implement Comparable.
    Alternatively, consider using Matchers in the expect of the blocTest rather than concrete state instances.
    

    I guess this is happening because of Equatable but how am I supposed to solve this? @felangel could you please help me with this one or does anyone has any insights on this? Thank you in advance.

    question waiting for response 
    opened by TusharRoy23 4
  • refactor(bloc): add core interfaces

    refactor(bloc): add core interfaces

    Status

    READY

    Breaking Changes

    NO

    Description

    • refactor(bloc): add core interfaces (closes #2994)

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [X] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [ ] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    feedback wanted pkg:bloc refactor 
    opened by felangel 2
  • Update Tutorial to match current code for `debounce`

    Update Tutorial to match current code for `debounce`

    Line 17 to 29 of https://github.com/felangel/bloc/blob/master/examples/flutter_infinite_list/lib/posts/bloc/post_bloc.dart

    Status

    READY/IN DEVELOPMENT/HOLD

    Breaking Changes

    YES | NO

    Description

    Type of Change

    • [ ] ✨ New feature (non-breaking change which adds functionality)
    • [ ] πŸ› οΈ Bug fix (non-breaking change which fixes an issue)
    • [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
    • [ ] 🧹 Code refactor
    • [ ] βœ… Build configuration change
    • [x] πŸ“ Documentation
    • [ ] πŸ—‘οΈ Chore
    opened by chonghorizons 0
  • [Question]

    [Question]

    Hello Felix, Sorry for bothering you with a question using the issues system, but this is bugging me for a while and I am not sure how to deal with it.

    For example, I am working on an app which has multiple tabs, which call the same api with different filters.

    To avoid building 6 Cubits just for just for a filter change, I've decided to use 1 cubit for all lists. The problem is when they emit, sometimes, they emit at the sametime and part of the data doesn't make it to the presentation layer.

    This is how I call the methods in question:

    Future<void> getAllWorkOrders() async {
        await listOpen();
        await listUnread();
        await listInProgress();
        await listOnHold();
        await listCompleted();
        await listAll();
      }
    

    A workaround to avoid them overlapping I do the following:

    Future<void> getAllWorkOrders() async {
        await listOpen();
        await repoDelay();
        await listUnread();
        await repoDelay();
        await listInProgress();
        await repoDelay();
        await listOnHold();
        await repoDelay();
        await listCompleted();
        await repoDelay();
        await listAll();
      }
    

    repoDelay() returns a Future.delayed(const Duration(milliseconds: 300)) so I give them time to process. So I am not sure:

    • is this the proper way to handle doing this sort of work?
    • is there another way?
    • is this a bug?
    • other?
    question waiting for response 
    opened by vadrian89 5
  • [Question] About bloc state management

    [Question] About bloc state management

    Hello @felangel, I am using bloc to create a Login Page and Home Page. I want to access and show the email of the user after logging in, in a different page (e.g Home Page or any other page).

    If i want to access the email variable in other Pages is it correct to put it under State Class? Is my structure below correct? :

    Here's the LoginState:

    part of 'login_cubit.dart';
    
    abstract class LoginState extends Equatable {
      final String? firstName;
      final String? lastName;
      final String? email;
    
      const LoginState({this.firstName, this.lastName, this.email});
    
      @override
      List<Object> get props => [];
    }
    
    class LoginInitial extends LoginState {}
    
    class LoginLoading extends LoginState {}
    
    class LoginError extends LoginState {
      final String errorMsg;
      const LoginError(this.errorMsg);
    
      @override
      List<Object> get props => [errorMsg];
    }
    
    class LoginAuthenticated extends LoginState {
      const LoginAuthenticated({firstName, lastName, email})
          : super(
              firstName: firstName,
              lastName: lastName,
              email: email,
            );
    }
    
    class LoginUnAuthenticate extends LoginState {}
    

    Here's my cubit, I am emitting the state in login() method:

    class LoginCubit extends Cubit<LoginState> {
      final AuthRepository repository;
      final RegisterCubit registerCubit;
      late final StreamSubscription blocSubscription;
    
      LoginCubit({required this.registerCubit, required this.repository})
          : super(LoginInitial()) {
        blocSubscription = registerCubit.stream.listen((state) {
          if (state is RegisterSuccess) {
            emit(LoginAuthenticated(
                firstName: state.firstName,
                lastName: state.lastName,
                email: state.email));
          }
        });
      }
    
    
      void login(String email, String password) async {
        emit(LoginLoading());
        AuthData data = await repository.login(email, password);
        if (!data.hasError) {
          UserProfile? user = await repository.currentUser();
          emit(
            LoginAuthenticated(
              firstName: user?.firstName,
              lastName: user?.lastName,
              email: user?.email,
            ),
          );
        } else {
          emit(LoginError(data.error));
        }
      }
    

    and I'm accessing the state variable using the code below: HomePage.dart:

       child: Builder(builder: (context) {
                      final firstname = context.select((LoginCubit cubit) => cubit.state.firstName);
                      return Text(
                        'Welcome $firstname!',
                        style: const TextStyle(
                          fontSize: 25,
                          color: Colors.white,
                        ),
                      );
                    }),
    

    Thanks in advance!!

    question 
    opened by marcqtan 0
  • [Question] How could I get event which triggered the method #onError(error, stackTrace)?

    [Question] How could I get event which triggered the method #onError(error, stackTrace)?

    I have several use cases in my project which could throw my custom exception. Each use case is presented as an Event in a specific Bloc. I need to find which event throw exceptions. So far I'm using #onEvent(event) to store the current event and #onError(error, stackTrace) to catch the exception. But when I migrate to Bloc v8.0.1 (which I find useful to make some events concurrently and repeatable) then the stored event in #onEvent(event) might not be the last event that thrown the exception. How could I handle this problem? For example, could you add an event parameter to here - such as onError(event, error, stackTrace)?

    question waiting for response 
    opened by dtvtkien 2
  • [question] how to test a bloc listener

    [question] how to test a bloc listener

    use case

    I would like to structure my tests in a way that allow me to

    • test listeners on cubit change
    • rely on underlying provider for dependency injections in listeners and cubit
    • test general context changes on cubit change (example navigation)

    issue

    afaik the typical implementation for this is a full blown widget test which may be undesirable when we don't actually need to test the widgets.

    I'm trying to streamline the process, so far with mixed results

    (if you want to run the code you can just clone the repo)

    code
    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_test/flutter_test.dart' as test;
    import 'mocks.dart';
    
    typedef ContextTester = FutureOr<void> Function(
      BuildContext context,
      test.WidgetTester tester,
    );
    
    extension BlocProviderGenetator<T> on Cubit<T> {
      BlocProvider<Cubit<T>> get provider => BlocProvider(
            create: (context) => this,
          );
    }
    
    extension BlocListProviderGenetator on Iterable<Cubit> {
      Iterable<BlocProvider> get providers sync* {
        for (final cubit in this) {
          yield cubit.provider;
        }
      }
    }
    
    void cubitContextTester({
      Iterable<BlocListener> listeners = const [],
      Iterable<Cubit> cubits = const [],
      Iterable<RepositoryProvider> repositories = const [],
      required String title,
      required ContextTester contextBlocTest,
    }) =>
        contextTester(
          title: title,
          tester: contextBlocTest,
          build: (key) => MultiRepositoryProvider(
            providers: [EmptyRepository(), ...repositories],
            child: Builder(
              builder: (context) => MultiBlocProvider(
                providers: [
                  ...[EmptyCubit(), ...cubits].providers
                ],
                child: Builder(
                  builder: (context) => MultiBlocListener(
                    listeners: [EmptyCubitListener(), ...listeners],
                    child: Builder(
                      builder: (context) => MaterialApp(home: SizedBox(key: key)),
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
    
    void contextTester({
      required String title,
      required Widget Function(Key) build,
      required ContextTester tester,
    }) {
      final key = UniqueKey();
      test.testWidgets(title, (_tester) async {
        await _tester.pumpWidget(build(key));
        final context = _tester.element(test.find.byKey(key));
        await tester(context, _tester);
      });
    }
    
    ///? source `https://github.com/felangel/bloc/blob/master/packages/bloc_test/lib/src/bloc_test.dart#L176`
    ///! modified
    ContextTester contextBlocTest<B extends BlocBase<State>, State>({
      FutureOr<void> Function(BuildContext)? setUp,
      required B Function(BuildContext) build,
      State Function(BuildContext)? seed,
      Function(B bloc)? act,
      Duration? wait,
      int? skip,
      dynamic Function(BuildContext)? expect,
      Function(B bloc)? verify,
      dynamic Function()? errors,
      FutureOr<void> Function(BuildContext)? tearDown,
    }) {
      return (context, tester) async {
        final unhandledErrors = <Object>[];
        var shallowEquality = false;
        await runZonedGuarded(
          () async {
            await setUp?.call(context);
            final states = <State>[];
            final bloc = build(context);
            // ignore: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member
            if (seed != null) bloc.emit(seed(context));
            final subscription = bloc.stream.skip(skip ?? 0).listen(states.add);
            try {
              await act?.call(bloc);
            } catch (error) {
              unhandledErrors.add(error);
            }
            if (wait != null) await Future<void>.delayed(wait);
            await Future<void>.delayed(Duration.zero);
            await bloc.close();
            if (expect != null) {
              final dynamic expected = expect(context);
              shallowEquality = '$states' == '$expected';
              try {
                test.expect(states, test.wrapMatcher(expected));
              } on test.TestFailure catch (e) {
                if (shallowEquality || expected is! List<State>) rethrow;
                final message =
                    '${e.message}\nexpected: $expected, actual: $states';
                // ignore: only_throw_errors
                throw test.TestFailure(message);
              }
            }
            await subscription.cancel();
            await verify?.call(bloc);
            await tearDown?.call(context);
          },
          (Object error, _) {
            if (shallowEquality && error is test.TestFailure) {
              // ignore: only_throw_errors
              throw test.TestFailure(
                '''${error.message}
    WARNING: Please ensure state instances extend Equatable, override == and hashCode, or implement Comparable.
    Alternatively, consider using Matchers in the expect of the blocTest rather than concrete state instances.\n''',
              );
            }
            if (!unhandledErrors.contains(error)) {
              // ignore: only_throw_errors
              throw error;
            }
          },
        );
        if (errors != null) {
          test.expect(unhandledErrors, test.wrapMatcher(errors()));
        }
      };
    }
    
    
    import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    
    class EmptyCubit extends Cubit<void> {
      EmptyCubit() : super(null);
    }
    
    class EmptyCubitListener extends BlocListener<EmptyCubit, void> {
      EmptyCubitListener({Key? key})
          : super(
              listener: (_, __) {},
              key: key ?? UniqueKey(),
            );
    }
    
    class EmptyRepository extends RepositoryProvider<void> {
      EmptyRepository({Key? key})
          : super(
              create: (_) => Null,
              key: key ?? UniqueKey(),
            );
    }
    
    
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_test/flutter_test.dart';
    import 'package:provider/provider.dart';
    
    import 'tester.dart';
    
    /// A `CounterCubit` which manages an `int` as its state.
    class CounterCubit extends Cubit<int> {
      /// The initial state of the `CounterCubit` is 0.
      CounterCubit() : super(0);
    
      /// When increment is called, the current state
      /// of the cubit is accessed via `state` and
      /// a new `state` is emitted via `emit`.
      void increment() => emit(state + 1);
    }
    
    void main() {
      group('CounterBloc', () {
        cubitContextTester(
          title: 'emits [] when nothing is added',
          cubits: [CounterCubit()],
          contextBlocTest: contextBlocTest<CounterCubit, int>(
            build: (context) => context.read<CounterCubit>(),
            expect: (context) => [],
          ),
        );
        cubitContextTester(
          title: 'emits [1] when Increment is added',
          cubits: [CounterCubit()],
          contextBlocTest: contextBlocTest<CounterCubit, int>(
            build: (context) => context.read<CounterCubit>(),
            act: (bloc) => bloc.increment(),
            expect: (context) => [],
          ),
        );
      });
    }
    
    
    pubspec
    name: context_bloc_test
    description: looking for a way to test cubit from context
    publish_to: 'none' 
    version: 1.0.0+1
    
    environment:
      sdk: '>=2.14.4 <3.0.0'
      flutter: ^2.5.3
    
    dependencies:
      flutter:
        sdk: flutter
      flutter_bloc: ^8.0.0
    
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
      flutter_lints: ^1.0.4
      bloc_test: ^9.0.1
    
    flutter:
      uses-material-design: true
    
    doctor
    [βœ“] Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-x64, locale en-EE)
        β€’ Flutter version 2.5.3 at /Users/francesco/fvm/versions/stable
        β€’ Upstream repository https://github.com/flutter/flutter.git
        β€’ Framework revision 18116933e7 (6 weeks ago), 2021-10-15 10:46:35 -0700
        β€’ Engine revision d3ea636dc5
        β€’ Dart version 2.14.4
    
    [βœ“] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
        β€’ Android SDK at /Users/francesco/Library/Android/sdk
        β€’ Platform android-31, build-tools 30.0.3
        β€’ Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
        β€’ Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
        β€’ All Android licenses accepted.
    
    [βœ“] Xcode - develop for iOS and macOS
        β€’ Xcode at /Applications/Xcode.app/Contents/Developer
        β€’ Xcode 13.1, Build version 13A1030d
        β€’ CocoaPods version 1.11.2
    
    [βœ“] Chrome - develop for the web
        β€’ Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [βœ“] Android Studio (version 2020.3)
        β€’ Android Studio at /Applications/Android Studio.app/Contents
        β€’ Flutter plugin can be installed from:
          πŸ”¨ https://plugins.jetbrains.com/plugin/9212-flutter
        β€’ Dart plugin can be installed from:
          πŸ”¨ https://plugins.jetbrains.com/plugin/6351-dart
        β€’ Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
    
    [βœ“] VS Code (version 1.62.3)
        β€’ VS Code at /Applications/Visual Studio Code.app/Contents
        β€’ Flutter extension version 3.28.0
    
    [βœ“] Connected device (2 available)
        β€’ macOS (desktop) β€’ macos  β€’ darwin-x64     β€’ macOS 12.0.1 21A559 darwin-x64
        β€’ Chrome (web)    β€’ chrome β€’ web-javascript β€’ Google Chrome 96.0.4664.55
    
    β€’ No issues found!
    
    logs
    ╭─[email protected] ~/development/context_bloc_test
    ╰─$ flutter test
    00:08 +0: CounterBloc emits [] when nothing is added
    ══║ EXCEPTION CAUGHT BY WIDGETS LIBRARY β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following ProviderNotFoundException was thrown building _NestedHook:
    Error: Could not find the correct Provider<EmptyCubit> above this EmptyCubitListener Widget
    
    This happens because you used a `BuildContext` that does not include the provider
    of your choice. There are a few common scenarios:
    
    - You added a new provider in your `main.dart` and performed a hot-reload.
      To fix, perform a hot-restart.
    
    - The provider you are trying to read is in a different route.
    
      Providers are "scoped". So if you insert of provider inside a route, then
      other routes will not be able to access that provider.
    
    - You used a `BuildContext` that is an ancestor of the provider you are trying to read.
    
      Make sure that EmptyCubitListener is under your MultiProvider/Provider<EmptyCubit>.
      This usually happens when you are creating a provider and trying to read it immediately.
    
      For example, instead of:
    
    

    Widget build(BuildContext context) { return Provider( create: (_) => Example(), // Will throw a ProviderNotFoundError, because context is associated // to the widget that is the parent of Provider<Example> child: Text(context.watch()), ), }

    
    consider using `builder` like so:
    
    

    Widget build(BuildContext context) { return Provider( create: (_) => Example(), // we use builder to obtain a new BuildContext that has access to the provider builder: (context) { // No longer throws return Text(context.watch()), } ), }

    
    If none of these solutions work, consider asking for help on StackOverflow:
    https://stackoverflow.com/questions/tagged/flutter
    
    The relevant error-causing widget was:
    _NestedHook
    _NestedHook:file:///Users/francesco/.pub-cache/hosted/pub.dartlang.org/nested-1.0.0/lib/nested.dart:103:31
    
    When the exception was thrown, this was the stack:
    #0      Provider._inheritedElementOf (package:provider/src/provider.dart:358:7)
    #1      Provider.of (package:provider/src/provider.dart:295:30)
    #2      ReadContext.read (package:provider/src/provider.dart:658:21)
    #3      _BlocListenerBaseState.initState (package:flutter_bloc/src/bloc_listener.dart:147:36)
    #4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4805:57)
    #5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #6      SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #13     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #20     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #27     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #28     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #29     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #30     _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #31     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #32     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #33     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #34     _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #41     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #48     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #55     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    #56     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #57     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #58     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #59     _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #60     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #61     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #62     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #63     _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #70     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #77     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #84     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #91     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #98     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #99     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #100    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #101    _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #102    Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #103    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #104    ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #105    _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #112    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #119    _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #126    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    #127    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #128    Element.updateChild (package:flutter/src/widgets/framework.dart:3422:20)
    #129    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1198:16)
    #130    RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1175:5)
    #131    RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1189:7)
    #132    Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #133    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:33)
    #134    AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1139:19)
    #135    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
    #136    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
    #137    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
    #138    AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1006:9)
    #141    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
    #142    AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:993:27)
    #143    WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:554:22)
    #146    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
    #147    WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:551:27)
    #148    contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:78:19)
    #149    contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:77:27)
    #150    testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:176:29)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided 5 frames from dart:async and package:stack_trace)
    
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    ══║ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following StateError was thrown running a test:
    Bad state: No element
    
    When the exception was thrown, this was the stack:
    #0      Iterable.single (dart:core/iterable.dart:520:25)
    #1      WidgetController.element (package:flutter_test/src/controller.dart:114:30)
    #2      contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:79:29)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided one frame from package:stack_trace)
    
    The test description was:
    emits [] when nothing is added
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    ══║ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following message was thrown:
    Multiple exceptions (2) were detected during the running of the current test, and at least one was
    unexpected.
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    00:08 +0 -1: CounterBloc emits [] when nothing is added [E]
    Test failed. See exception logs above.
    The test description was: emits [] when nothing is added
    
    00:08 +0 -1: CounterBloc emits [1] when Increment is added
    ══║ EXCEPTION CAUGHT BY WIDGETS LIBRARY β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following ProviderNotFoundException was thrown building _NestedHook:
    Error: Could not find the correct Provider<EmptyCubit> above this EmptyCubitListener Widget
    
    This happens because you used a `BuildContext` that does not include the provider
    of your choice. There are a few common scenarios:
    
    - You added a new provider in your `main.dart` and performed a hot-reload.
    To fix, perform a hot-restart.
    
    - The provider you are trying to read is in a different route.
    
    Providers are "scoped". So if you insert of provider inside a route, then
    other routes will not be able to access that provider.
    
    - You used a `BuildContext` that is an ancestor of the provider you are trying to read.
    
    Make sure that EmptyCubitListener is under your MultiProvider/Provider<EmptyCubit>.
    This usually happens when you are creating a provider and trying to read it immediately.
    
    For example, instead of:
    
    

    Widget build(BuildContext context) { return Provider( create: (_) => Example(), // Will throw a ProviderNotFoundError, because context is associated // to the widget that is the parent of Provider<Example> child: Text(context.watch()), ), }

    
    consider using `builder` like so:
    
    

    Widget build(BuildContext context) { return Provider( create: (_) => Example(), // we use builder to obtain a new BuildContext that has access to the provider builder: (context) { // No longer throws return Text(context.watch()), } ), }

    
    If none of these solutions work, consider asking for help on StackOverflow:
    https://stackoverflow.com/questions/tagged/flutter
    
    The relevant error-causing widget was:
    _NestedHook
    _NestedHook:file:///Users/francesco/.pub-cache/hosted/pub.dartlang.org/nested-1.0.0/lib/nested.dart:103:31
    
    When the exception was thrown, this was the stack:
    #0      Provider._inheritedElementOf (package:provider/src/provider.dart:358:7)
    #1      Provider.of (package:provider/src/provider.dart:295:30)
    #2      ReadContext.read (package:provider/src/provider.dart:658:21)
    #3      _BlocListenerBaseState.initState (package:flutter_bloc/src/bloc_listener.dart:147:36)
    #4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4805:57)
    #5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #6      SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #13     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #20     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #27     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #28     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #29     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #30     _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #31     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #32     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #33     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #34     _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #41     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #48     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #55     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    #56     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #57     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #58     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #59     _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #60     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #61     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #62     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #63     _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #70     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #77     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #84     _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #91     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #98     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #99     Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
    #100    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
    #101    _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:495:11)
    #102    Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #103    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
    #104    ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
    #105    _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:395:11)
    ...     Normal element mounting (7 frames)
    #112    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    ...     Normal element mounting (7 frames)
    #119    _NestedHookElement.mount (package:nested/nested.dart:187:11)
    ...     Normal element mounting (7 frames)
    #126    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
    #127    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
    #128    Element.updateChild (package:flutter/src/widgets/framework.dart:3422:20)
    #129    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1198:16)
    #130    RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1175:5)
    #131    RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1189:7)
    #132    Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
    #133    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:33)
    #134    AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1139:19)
    #135    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
    #136    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
    #137    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
    #138    AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1006:9)
    #141    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
    #142    AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:993:27)
    #143    WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:554:22)
    #146    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
    #147    WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:551:27)
    #148    contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:78:19)
    #149    contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:77:27)
    #150    testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:176:29)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided 5 frames from dart:async and package:stack_trace)
    
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    ══║ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following StateError was thrown running a test:
    Bad state: No element
    
    When the exception was thrown, this was the stack:
    #0      Iterable.single (dart:core/iterable.dart:520:25)
    #1      WidgetController.element (package:flutter_test/src/controller.dart:114:30)
    #2      contextTester.<anonymous closure> (file:///Users/francesco/development/context_bloc_test/test/tester.dart:79:29)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided one frame from package:stack_trace)
    
    The test description was:
    emits [1] when Increment is added
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    ══║ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    The following message was thrown:
    Multiple exceptions (2) were detected during the running of the current test, and at least one was
    unexpected.
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    00:08 +0 -2: CounterBloc emits [1] when Increment is added [E]
    Test failed. See exception logs above.
    The test description was: emits [1] when Increment is added
    
    00:08 +0 -2: Some tests failed.
    

    bottomline

    I'd appreciate some suggestion on a better approach or if this approach makes any sense I could use some help to fix the issue

    thank you

    question waiting for response 
    opened by aoatmon 5
  • refactor: stop losing the original stack trace from dart 2.16

    refactor: stop losing the original stack trace from dart 2.16

    You must stop losing the original source stack trace like this (just for example):

    https://github.com/felangel/bloc/blob/a3a9b2dba6546480d4ea26931ed024f274b9a7a9/examples/flutter_firebase_login/packages/authentication_repository/lib/src/authentication_repository.dart#L206-L210

    it's big trouble, to read exceptions without source stacktraces, especially in crashlytics or sentry like logs

    from dart 2.16 you must use Error.throwWithStackTrace like this:

    //@dart=2.16
    
    ...
    
    } on FirebaseAuthException catch (e, stackTrace) {
      Error.throwWithStackTrace(
        SignUpWithEmailAndPasswordFailure.fromCode(e.code),
        stackTrace,
      );
    }
    

    also, instead:

    } catch (_) {
    

    you must write:

    } on Object {
    

    or:

    } on Object catch (error, stackTrace) {
    
    example refactor 
    opened by PlugFox 5
  • refactor: Π°dding interfaces

    refactor: Π°dding interfaces

    Why does the entire architectural library still lack a interfaces? Whats about Dependency inversion principle and interface segregation principle?

    Why BlocBuilder depends on BlocBase and not on IStateObservable something like this:

    /// {@template i_state_observable}
    /// An interface to observe states stream.
    /// Current [state] available as property.
    /// State subject to implement the Observer (Dependents) pattern
    /// {@endtemplate}
    abstract class IStateObservable<T extends Object?> {
      /// The current [state].
      T get state;
    
      /// The state stream.
      StateStream<T> get stream;
    }
    

    BlocBuilder, BlocListener, BlocProvider, BlocConsumer really needs addError, emit, onChange, onError and others methods and callbacks?

    Also you need something like this:

    /// {@template i_bloc_subject}
    /// Interface to observe states stream.
    /// Current [state] available as property.
    /// [Bloc] Subject to implement the Publisher/Subscriber pattern
    /// {@endtemplate}
    abstract class IBlocSubject<State extends Object?>
        implements IStateObservable<State> {
      /// Updates the [state] to the provided [state].
      /// [setState] does nothing if the instance has been closed.
      @protected
      @mustCallSuper
      void setState(State state);
    
      /// Called whenever a [change] occurs with the given [change].
      /// A [change] occurs when a new `state` is emitted.
      /// [onChange] is called before the `state` of the `bloc` is updated.
      /// [onChange] is a great spot to add logging/analytics for a specific `bloc`.
      ///
      /// **Note: `super.onChange` should always be called first.**
      /// ```dart
      /// @override
      /// void onChange(Change change) {
      ///   // Always call super.onChange with the current change
      ///   super.onChange(change);
      ///
      ///   // Custom onChange logic goes here
      /// }
      /// ```
      ///
      /// See also:
      ///
      /// * [IBlocObserver] for observing [Bloc] behavior globally.
      @protected
      @mustCallSuper
      @visibleForOverriding
      void onChange(Change<State> change);
    }
    
    /// {@template i_bloc_sink}
    /// A [Bloc] Sink interface that accepts events both synchronously
    /// and asynchronously.
    ///
    /// The [IBlocSink] methods can't be used while the [addStream] is called.
    /// As soon as the [addStream]'s [Future] completes with a value, the
    /// [EventSink] methods can be used again.
    ///
    /// If [addStream] is called after any of the [EventSink] methods, it'll
    /// be delayed until the underlying system has consumed the data added by the
    /// [EventSink] methods.
    ///
    /// When [EventSink] methods are used, the [done] [Future] can be used to
    /// catch any errors.
    ///
    /// When [close] is called, it will return the [done] [Future].
    /// {@endtemplate}
    abstract class IBlocSink<Event extends Object?> implements StreamSink<Event> {
      /// Reports an [error] which triggers [onError] with an optional [StackTrace].
      /// If [close] has already been called, any subsequent calls to [addError]
      /// will be ignored and will not result in any subsequent state changes.
      @override
      @protected
      @mustCallSuper
      void addError(Object error, [StackTrace? stackTrace]);
    
      /// Notifies the [Bloc] of a new [event]
      /// If [close] has already been called, any subsequent calls to [add] will
      /// be ignored and will not result in any subsequent state changes.
      @override
      void add(Event event);
    
      /// Called whenever an [event] is [add]ed to the [Bloc].
      /// A great spot to add logging/analytics at the individual [Bloc] level.
      ///
      /// **Note: `super.onEvent` should always be called first.**
      /// ```dart
      /// @override
      /// void onEvent(Event event) {
      ///   // Always call super.onEvent with the current event
      ///   super.onEvent(event);
      ///
      ///   // Custom onEvent logic goes here
      /// }
      /// ```
      ///
      /// See also:
      ///
      /// * [IBlocObserver.onEvent] for observing events globally.
      ///
      @protected
      @mustCallSuper
      @visibleForOverriding
      void onEvent(Event event);
    
      /// Called whenever an [error] occurs and notifies [IBlocObserver.onError].
      ///
      /// In debug mode, [onError] throws a [BlocUnhandledErrorException] for
      /// improved visibility.
      ///
      /// In release mode, [onError] does not throw and will instead only report
      /// the error to [IBlocObserver.onError].
      ///
      /// **Note: `super.onError` should always be called last.**
      /// ```dart
      /// @override
      /// void onError(Object error, StackTrace stackTrace) {
      ///   // Custom onError logic goes here
      ///
      ///   // Always call super.onError with the current error and stackTrace
      ///   super.onError(error, stackTrace);
      /// }
      /// ```
      @protected
      @mustCallSuper
      @visibleForOverriding
      void onError(Object error, StackTrace stackTrace);
    
      /// Closes the `event` and `state` `Streams`.
      /// This method should be called when a [Bloc] is no longer needed.
      /// Once [close] is called, `events` that are [add]ed will not be
      /// processed.
      /// In addition, if [close] is called while `events` are still being
      /// processed, the [Bloc] will finish processing the pending `events`.
      @override
      @mustCallSuper
      @visibleForOverriding
      Future<void> close();
    
      /// Pass all [eventStream] events to the [Bloc]
      /// If [close] has already been called, any subsequent calls to [addStream]
      /// will be ignored and will not result in any subsequent state changes.
      @override
      Future<void> addStream(Stream<Event> eventStream);
    
      /// Return a future which is completed when the [IBlocSink] is finished.
      ///
      /// If the `IBlocSink` fails with an error,
      /// perhaps in response to adding events using [add], [addStream], [addError]
      /// or [close], the [done] future will complete with that error.
      ///
      /// Otherwise, the returned future will complete when either:
      ///
      /// * all events have been processed and the sink has been closed, or
      /// * the sink has otherwise been stopped from handling more events
      ///   (for example by canceling a stream subscription).
      @override
      Future<void> get done;
    }
    
    /// {@template i_bloc}
    /// An interface to implement the Publisher/Subscriber pattern for [Bloc].
    /// Takes a `Stream` of `Events` as input
    /// and transforms them into a `Stream` of `States` as output.
    /// {@endtemplate}
    abstract class IBloc<Event extends Object?, State extends Object?>
        implements IBlocSink<Event>, IBlocSubject<State> {
      /// Transforms the [events] stream along with a [transitionFn] function into
      /// a `Stream<Transition>`.
      /// Events that should be processed by [mapEventToState] need to be passed to
      /// [transitionFn].
      /// By default `asyncExpand` is used to ensure all [events] are processed in
      /// the order in which they are received.
      /// You can override [transformEvents] for advanced usage in order to
      /// manipulate the frequency and specificity with which [mapEventToState] is
      /// called as well as which [events] are processed.
      ///
      /// For example, if you only want [mapEventToState] to be called on the most
      /// recent [Event] you can use `switchMap` instead of `asyncExpand`.
      ///
      /// ```dart
      /// @override
      /// Stream<Transition<Event, State>> transformEvents(events, transitionFn) {
      ///   return events.switchMap(transitionFn);
      /// }
      /// ```
      ///
      /// Alternatively, if you only want [mapEventToState] to be called for
      /// distinct [events]:
      ///
      /// ```dart
      /// @override
      /// Stream<Transition<Event, State>> transformEvents(events, transitionFn) {
      ///   return super.transformEvents(
      ///     events.distinct(),
      ///     transitionFn,
      ///   );
      /// }
      /// ```
      @visibleForOverriding
      Stream<Transition<Event, State>> transformEvents(
        Stream<Event> events,
        TransitionFunction<Event, State> transitionFn,
      );
    
      /// Must be implemented when a class extends [Bloc].
      /// [mapEventToState] is called whenever an [event] is [add]ed
      /// and is responsible for converting that [event] into a new [state].
      /// [mapEventToState] can `yield` zero, one, or multiple states for an event.
      @protected
      @visibleForOverriding
      Stream<State> mapEventToState(Event event);
    
      /// Called whenever a [transition] occurs with the given [transition].
      /// A [transition] occurs when a new `event` is [add]ed and [mapEventToState]
      /// executed.
      /// [onTransition] is called before a [Bloc]'s [state] has been updated.
      /// A great spot to add logging/analytics at the individual [Bloc] level.
      ///
      /// **Note: `super.onTransition` should always be called first.**
      /// ```dart
      /// @override
      /// void onTransition(Transition<Event, State> transition) {
      ///   // Always call super.onTransition with the current transition
      ///   super.onTransition(transition);
      ///
      ///   // Custom onTransition logic goes here
      /// }
      /// ```
      ///
      /// See also:
      ///
      /// * [IBlocObserver.onTransition] for observing transitions globally.
      ///
      @protected
      @mustCallSuper
      @visibleForOverriding
      void onTransition(Transition<Event, State> transition);
    
      /// Transforms the `Stream<Transition>` into a new `Stream<Transition>`.
      /// By default [transformTransitions] returns
      /// the incoming `Stream<Transition>`.
      /// You can override [transformTransitions] for advanced usage in order to
      /// manipulate the frequency and specificity at which `transitions`
      /// (state changes) occur.
      ///
      /// For example, if you want to debounce outgoing state changes:
      ///
      /// ```dart
      /// @override
      /// Stream<Transition<Event, State>> transformTransitions(
      ///   Stream<Transition<Event, State>> transitions,
      /// ) {
      ///   return transitions.debounceTime(Duration(seconds: 1));
      /// }
      /// ```
      @protected
      @visibleForOverriding
      Stream<Transition<Event, State>> transformTransitions(
        Stream<Transition<Event, State>> transitions,
      );
    }
    

    and much more, like ISink, IDisposal, ITransition, IChange, IEventConsumer, IStateEmiter.

    waiting for response pkg:bloc refactor 
    opened by PlugFox 21
Releases(replay_bloc-v0.2.1)
Owner
Felix Angelov
software engineer by day, software engineer by night.
Felix Angelov
Another state management solution

VxState VxState is a state management library built for Flutter apps with focus on simplicity. It is inspired by StoreKeeper & libraries like Redux, V

Pawan Kumar 29 Oct 6, 2021
A flutter boilerplate project with GetX state management.

flutter_getx_boilerplate Languages: English (this file), Chinese. Introduction During my study of Flutter, I have been using the flutter_bloc state ma

Kevin Zhang 141 Nov 24, 2021
Flutter MVU architecture/state management package

mvu_flutter No mutability. No builders. No connectors. No reducers. No StreamControllers and subscription management. A truly declarative state manage

Yakov Karpov 7 Jul 29, 2021
Simple global state management for Flutter

Slices Slices is a minimalist state manegement, focused specifically for applications that needs a global state where different "pieces" of the applic

Erick 5 Jun 15, 2021
A simple way to access state while robust and testable.

A state-management library that: catches programming errors at compile time rather than at runtime removes nesting for listening/combining objects ens

Remi Rousselet 2.1k Nov 22, 2021
A lightweight, yet powerful way to bind your application state with your business logic.

binder A lightweight, yet powerful way to bind your application state with your business logic. The vision As other state management pattern, binder a

Romain Rastel 164 Nov 17, 2021
Manage the state of your widgets using imperative programming concepts.

Imperative Flutter Manage the state of your widgets using imperative programming concepts. Setup Intall imperative_flutter package in pubspec.yaml dep

Jeovane Santos 4 Apr 23, 2021
Trip management mobile Application

HereYouGO Trip management mobile Application This app will help you Track your expense during your trips. Track your trip destinations and the sub tri

Krupali Mehta 4 Aug 1, 2021
(Complete flutter application) Exam and training app as social media, prepared with Firebase backend services, Bloc State management, Singleton design pattern, Unit and widget tests, firebase mocking, Custom local libraries, etc.

(Complete flutter application) Exam and training app as social media, prepared with Firebase backend services, Bloc State management, Singleton design pattern, Unit and widget tests, firebase mocking, Custom local libraries, etc.

Ismael Shakverdiev 48 Nov 25, 2021
Flutter Login Page Bloc Pattern App Flutter Login Page Bloc Pattern App

gdgbloc A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

Pawan Kumar 95 Oct 12, 2021
A Simple Todo app design in Flutter to keep track of your task on daily basis. Its build on BLoC Pattern. You can add a project, labels, and due-date to your task also you can sort your task on the basis of project, label, and dates

WhatTodo Life can feel overwhelming. But it doesn’t have to. A Simple To-do app design in flutter to keep track of your task on daily basis. You can a

Burhanuddin Rashid 908 Dec 2, 2021
Okan YILDIRIM 34 Nov 19, 2021
App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and less verbose.

App HTTP Client App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and le

Joanna May 25 Nov 25, 2021
Responsive Sizer helps implement are responsive layout by providing helper widgets and extensions

Responsive Sizer Responsive Sizer helps implement a responsive layout by providing helper widgets and extensions Content Installation Parameters Take

CoderUni 31 Oct 21, 2021
Minimalist Flutter Todo App, built using BLoC pattern

Deer Minimalist Todo Planner app built around the idea of efficiency and clean aesthetic. Showcase Development Deer uses BLoC (Business Logic Componen

Aleksander WoΕΊniak 292 Nov 14, 2021
A starter kit for beginner learns with Bloc pattern, RxDart, sqflite, Fluro and Dio to architect a flutter project. This starter kit build an App Store app as a example

Flutter Starter Kit - App Store Example A starter kit for beginner learns with Bloc pattern, RxDart, sqflite, Fluro and Dio to architect a flutter pro

kw101 596 Nov 28, 2021
MobX for the Dart language. Hassle-free, reactive state-management for your Dart and Flutter apps.

Language: English | PortuguΓͺs | Chinese mobx.dart MobX for the Dart language. Supercharge the state-management in your Dart apps with Transparent Func

MobX 2k Nov 27, 2021
Another state management solution

VxState VxState is a state management library built for Flutter apps with focus on simplicity. It is inspired by StoreKeeper & libraries like Redux, V

Pawan Kumar 29 Oct 6, 2021
A flutter boilerplate project with GetX state management.

flutter_getx_boilerplate Languages: English (this file), Chinese. Introduction During my study of Flutter, I have been using the flutter_bloc state ma

Kevin Zhang 141 Nov 24, 2021
Flutter MVU architecture/state management package

mvu_flutter No mutability. No builders. No connectors. No reducers. No StreamControllers and subscription management. A truly declarative state manage

Yakov Karpov 7 Jul 29, 2021
Music player application for android. It's uses MVVM architecture and Provider & ValueNotifier state management.

music-player-flutter Flutter music player application which is my personal project published to play store. Project structures are as following,

null 23 Oct 31, 2021
Simple global state management for Flutter

Slices Slices is a minimalist state manegement, focused specifically for applications that needs a global state where different "pieces" of the applic

Erick 5 Jun 15, 2021
Cryptocurrency App with MVP Design Pattern to track all the coins data in realtime for android & iOS . Written in dart using Flutter SDK.

Flutter CryptoCurrency App (MVP) Cryptocurrency App with MVP design pattern to track all the coins data in realtime for android & iOS . Written in dar

Pawan Kumar 258 Nov 29, 2021
The app to demo animation with Flutter by implement Facebook reactions

Facebook Reactions Animation Description The app to demo animation with Flutter by implement Facebook reactions. Watch the demo video for more clarity

Duy Tran 260 Nov 28, 2021
A quick sample app on how to implement a friend list and a profile page in Flutter.

FlutterMates All code resides in the /lib folder: there's no Android / iOS specific code needed. The article, slides and how this came to be, is here.

Codemate Ltd 480 Nov 15, 2021
A Flutter application to demonstrate how to implement Google maps and its advanced options in a flutter app.

google_maps_flutter_example A new Flutter application to demonstrate how to implement flutter google maps in a flutter application and perfoem advance

Hesham Erfan 26 Oct 30, 2021
Challenge yourself every weekend with flutter. Join me to implement challenging UI & digital designs using Flutter.

Weekend With Flutter This is my new challenge. Every weekend, I want to implement challenging UI & digital designs using Flutter. you can join me with

Payam Zahedi 16 Nov 8, 2021
Beautiful Nike Web Design Concept With Flutter Beautiful Nike Web Design Concept With Flutter

flutter_web_nike A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Pawan Kumar 22 Nov 18, 2021
A new Flutter package which helps developers in creating walkthrough of their app.

flutter_walkthrough A new Flutter package for both android and iOS which helps developers in creating animated walkthrough of their app. Show some ❀️

Pawan Kumar 122 Oct 20, 2021