GithubHelp home page GithubHelp logo

felangel / bloc Goto Github PK

View Code? Open in Web Editor NEW
11.4K 176.0 3.4K 58.23 MB

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

Home Page: https://bloclibrary.dev

License: MIT License

Dart 73.90% Java 0.24% Objective-C 0.02% Kotlin 5.59% TypeScript 5.94% JavaScript 0.18% Ruby 0.40% Swift 0.61% C++ 6.50% C 0.41% HTML 0.88% CMake 5.35%
flutter dart dartlang flutter-package bloc dart-web dart-library state-management library angulardart

bloc's Introduction

Bloc

build codecov Star on Github 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
bloc_concurrency pub package
flutter_bloc pub package
angular_bloc pub package
hydrated_bloc pub package
replay_bloc pub package
sealed_flutter_bloc pub package

Sponsors

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


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.
  • 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.
  • Fluttersaurus - an example of how to use the bloc and flutter_bloc packages to create a thesaurus app -- made for Bytconf Flutter 2020.
  • I/O Photo Booth - an example of how to use the bloc and flutter_bloc packages to create a virtual photo booth web app -- made for Google I/O 2021.
  • I/O Pinball - an example of how to use the bloc and flutter_bloc packages to create a pinball web app -- made for Google I/O 2022.

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

bloc's People

Contributors

abhishek01039 avatar alestiago avatar alisson-suzigan avatar basilex avatar cxdtreeg avatar dawidd6 avatar dependabot[bot] avatar doubletrio avatar duan-daniel avatar felangel avatar gene-dana avatar hkuczynski avatar ichabanivan avatar jakecastelli avatar jonathankao97 avatar jorgecoca avatar kingdarboja avatar kylefin avatar marcossevilla avatar maximveksler avatar mayursmahajan avatar mzdm avatar netantho avatar orsenkucher avatar rodrigobastosv avatar stefanspeterdev avatar tenhobi avatar thisisyusub avatar victoruvarov avatar zepfietje avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bloc's Issues

How should I clear "state"?

There's a "message" variable inside the state, I used to Toast the "message" whenever it's not null. So, whenever I trigger a Navigator.push(), previous page rebuild, then the state contain non-null "message", it triggered the Toast again.

Is it possible to merge blocs

Let's suppose I have two blocs Router and Model and I have to create gui based on the state of both of them with router I choose Widget that will be rendered and I have to pass model to each view widget.
Is it possible to easily merge two Bloc s Like for instance ZipStream.

Change the parameters of mapEventToState

Is your feature request related to a problem? Please describe.
The Bloc class type signature as well as the onTransition method is <E, S>. But the mapEventToState parameters are (S, E).

Describe the solution you'd like
It would be more consistent if the mapEventToState method would follow the signature of the rest of the package and also have (E event, S state) instead of (S state, E event).

Should one bloc handle different types of events?

Hi Felix, I am currently learning bloc and have a question regarding the practice of using bloc. My question is that should one bloc handle different types of events?

For example, I have several CRUD operations to my database. So the events could be loading posts, adding posts, upvoting, adding comments, etc. These events could have corresponding states like LoadPostsSuccess/Failure, AddPostSuccess/Failure, etc. I am wondering whether I should use one single DBBloc to handle all these events/states or should I use LoadPostBloc, AddPostBloc, and UpvoteBloc to handle these?

Thank you in advance for your help!

Example of working with complex State objects in angular_bloc

Hi! Can you show me how to bind the state object in HTML file? In the angular_counter_example the state is a simple int and you bind this state to view like this:

<h2>Current Count: {{ counterBloc | bloc }}</h2>

If my state seems like this:

class MyState {
   num foo;
   num bar;
}

How can I work with this state in HTML view? Is necesary to use the BlocPipe?

Thanks!

[Question] 1 Event with multiple update on State

Hi,
thanks for the great work on this bloc library (or maybe framework).

I'm now trying to follow the instruction on your tutorial and I had a question.

So , is there way to update state multiple time with single event?
In other words is there way to behave as hot stream (or Observable) ?

For example on tutorial, I was wondering how to manage "Loading State".
Simple way which I came up was first update with PostLoading and whenever the data was fetched update with PostLoaded from single Fetch event. Is this possible with current API ?

code example

@override
  Stream<PostState> mapEventToState(
    PostState currentState,
    PostEvent event,
  ) async* {
    if (event is Fetch && !_hasReachedMax(currentState)) {
      try {
        if (currentState is PostUninitialized) {
          final posts = await _fetchPosts(0, 20);
          // want to return PostLoading();
          yield PostLoaded(posts: posts, hasReachedMax: false);
        }
        if (currentState is PostLoaded) {
          // want to return PostLoading();
          final posts = await _fetchPosts(currentState.posts.length, 20);
          yield posts.isEmpty ? currentState.copyWith(hasReachedMax: true) : PostLoaded(posts: currentState.posts + posts, hasReachedMax: false);
        }
      } catch (_) {
        yield PostError();
      }
    }
  }

Anyway thanks for the awesome work.

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] How to inject service instead of using UserRepository ?

In flutter_login exemple, UserRepository creation is into AppState class.

If you need to use network service for authentication (e.g. firebase_auth), when writing tests, there is no easy way to mock UserRepository in the current implementation.

How to inject UserRepository in the current implementation ? with another Bloc ?

Let's assume the replacement of UserRepository by Firebase Authentication.
Then, how to share currentUser after login ? with another Bloc ?

[Question] Why did you change from StatefullWidget to InheritedWidget?

Hi, I saw that you have changed from StatefulWidget to InheritedWidget because you haven't implemented the dispose method. #57

Why did you change from stateful to inherited if you could implement dispose method as the Didier version?
https://www.didierboelens.com/2018/12/reactive-programming---streams---bloc---practical-use-cases/

The Didier approach is good because we don't need to create StatefulWidget to use the dispose method only.

Need lifecycle on bloc

hi author, i want to place some components in bloc and dispose them when bloc destroyed.
i hope initState() and dispose() featured will be support

Doc bug: Constant constructor can't call non-constant super constructor of 'Equatable

At page:

https://felangel.github.io/bloc/#/flutterinfinitelisttutorial?id=data-model

The syntax

  const Post({this.id, this.title, this.body}) : super([id, title, body]);

looks like no more valid, it throws 2 errors

Constant constructor can't call non-constant super constructor of 'Equatable'.

and

Initializer expressions in constant constructors must be constants.

It seems fixable as

Post({this.id, this.title, this.body}) : super([id, title, body]);

But I don't know if removing leading const changes the behaviours. If add

Can you change bloc state's type to ValueObservable<State> ?

Is your feature request related to a problem? Please describe.
no

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

In rxdart 0.19.0, the ValueObservable type is provided.
I recommend changing
"Stream get state => _stateSubject.stream;"
to
"ValueObservable get state => _stateSubject.stream;".
This way, in StreamBuilder , initialData can use your_bloc.state.value
Please refer to "https://twitter.com/filiphracek/status/1050798900968181761"

Should representing different state using sum types

Is your feature request related to a problem? Please describe.
In the Login Tutorial, AuthenticationState is represented by three finals: isInitializing, isLoading and isAuthenticated. This seems a bad idea because they can be combined in many illegal combinations, like isLoading = true && isAuthenticated = true.

Describe the solution you'd like
We should always represent discrete states using sum types. Since Dart doesn't have it yet, we can simulate using classes like this (taken from official examples of rxdart):

class SearchState {}

class SearchLoading extends SearchState {}

class SearchError extends SearchState {}

class SearchNoTerm extends SearchState {}

class SearchPopulated extends SearchState {
  final SearchResult result;

  SearchPopulated(this.result);
}

class SearchEmpty extends SearchState {}

Additional context
I'm sorry if this may sound like a rant. But the lack of sum types is just so disappointing when it comes to state management. While the same ideas can be coded both more secure and more expressive in modern languages like TypeScript and Swift, in Dart we have to make do.

Help

any this code?

static T of<T extends BlocBase>(BuildContext context){
    final type = _typeOf<BlocProvider<T>>();
    BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
    return provider.bloc;
  }

tks.

mapEventToState with oldState

Hi

if i need the oldState in order to create the new state how can i do that without state.take(1).then()...
can you implement mapEventToState(State,Event) ?

maybe just save the state locally in each mapEventToState call ?

BlocBuilder builder function not called after pushReplacementNamed

Describe the bug
Using the Login tutorial, after navigate to another page using pushReplacementNamed, the _AppState BlocBuilder builder function was not called when I dispatch a new state from the new Page.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new Page and put a button to dispatch authenticationBloc.dispatch(LoggedOut()); using the global AuthenticationBloc;
  2. From Home or Login, navigate to new page using pushReplacementNamed;
  3. Press the button in the new page;
  4. See that the transition was called but the BlocBuilder builder function in the _AppState was not;

Expected behavior
From new page dispatch LoggedOut and change the MaterialApp home to LoadingIndicator and LoginPage after;

Additional context
I'm using the last version ^0.5.3 and testing in iOS simulator.

Generator

Is your feature request related to a problem? Please describe.
The way this works is pretty cool.
For large apps you end up with alot of code to maintain and i was thinking about a generator to help.

Describe the solution you'd like
There is a bloc generator here and its pretty nice.
https://github.com/CallumIddon/bloc_generator

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Have a looksie and see what you think.

Minor Readme issue

Just want to say this is a great package and has been really helpful in helping me implement the bloc pattern.

I think I noticed a really small mistake in the Readme.
Where it says yield LoginState.error(error.toString()); (unsure of the actual line number) I think it should be yield LoginState.failure(error.toString());.

If that's the case, happy to raise a PR if you want me to?

Missing ")" in fluttercountertutorial.md

The missing ")" on line 88 in the tutorial makes the example not compile

To Reproduce

  1. Copy the source code from the tutorial to and IDE

Expected behavior
The example should compile

Redux ?

As much as I like your library, correct me if I'm wrong but I think it is much closer to the Redux architecture than it is to a Bloc one.
Although there is no clear definition of a Bloc yet, from what I've gathered it's much more reactive, should use Sinks are input, and Streams as output.
While this library is used to convert Events (like strongly-typed Redux Actions) into a single State output, using the mapEventToState reducer function, which is very cool in its way, just not what a Bloc architecture is.

https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/

Initiate new event of different bloc at transition

Is your feature request related to a problem? Please describe.

I wish to listen to event like startLocationService and than init a new event/s (like log)

Describe the solution you'd like

I was thinking of mingling events at the BlockSupervisor. But given that, I just lately started with dart and flutter so I am not sure of anything.

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

Web Support

Very nice package!

I would like to know if this package will be compatible with Dart for Web, like AngularDart.

Thanks in advance.

How would I use Navigator with this?

For example, I have a button that would normally have the Navigator call in the onPressed. Using this Bloc pattern, I would dispatch that button click event and then what? What runs the Navigator call?

Proposition for some improvements over the examples

First, I want to thank you for your great job. Nevertheless I want to share my experience trying to learn from you example projects.

  1. A get package over pubspec.yaml inside flutter_github_search outputs:
    Because every version of flutter_test from sdk depends on meta 1.1.6 and every version of common_github_search from path depends on meta ^1.1.7, flutter_test from sdk is incompatible with common_github_search from path. ... pub get failed (1).

*If I edit pubspec.yaml inside ../common_github_search and change for meta 1.1.6, the get packages works... I think.

Solution: Maybe talk about it in the README, eg how to upgrade flutter to meta 1.1.7, if not possible maybe not 'metaying' to bleeding edge...)

  1. If I open flutter_github_search (vsc or android studio) everything referencing -> import 'package:common_github_search/common_github_search.dart'; cannot be seen. Seems logical to me, common_github_search.dart is located upward.

Ok then what about I open one up, github_search? Dear god, vsc is choking like there is no tomorrow.

Solution: Maybe talk about it in the README, eg. what is to be done to handle this 'exotic' project arrangement: for a toy example project this is arguably 'unwelcoming'. I still haven't found how to run this one...

  1. If possible, for a future demo, I would tone down the 'abstractions' around the exemplification of your bloc pattern library. The github search example is great as it demos network calls but it is threaded with what I would call didactic noise, eg heavy wrapping in classes (that I suspect could be slimmed out), a lot of redirection through 'one class one file', helper functions etc. From a newcomer perspective, I just want to understand the 'core' mechanics of your lib (bloc pattern, BlocBuilder, events, state, your bloc interface etc) for relatively complex tasks, eg rest call handling. Everything around that is just potentially tripping wire. I get it its bread and butter for someone acquainted with flutter, but for a total newcomer it feels heavy. My two cents.

Thx for your time and concern,
ohenley

Using landing page before login page, state update but page not redirected

Based on original example for not authorize user will see a login page, but i did little bit modified instead of not authenticate user will see a landing page. User now pick button option for login (consist many option for login email/google/etc) then it will open login page. The problem is after login success the page still at login page not redirected to authenticate page i set. Only work if i click back button of restart app
`class LandingPage extends StatelessWidget {
final UserRepository userRepository;

LandingPage({Key key, this.userRepository}) : super(key: key);

@OverRide
Widget build(BuildContext context) {

return Scaffold(
body: Container(
child: Center(
child: RaisedButton(
onPressed: (){

        Navigator.push(context, MaterialPageRoute(
            builder: (context) => LoginPage(userRepository: userRepository,)
        ));
      },
  ),
),

),
) ;
}

}`

@override Transfom with different debounce

Hi all, Thanks for this framwork. It is clear and simple :)

I have a question. how would you recommend to implement different Debounce on the stream input in the transform bloc method. immagine A have a input test field for search -> debounce 500ms but a submit button -> No debounce?

Again thanks for this great work.

Transform Example

Can you please provide an example of overriding transform? Specifically debouncing a certain event (e.g. Search), but not other events in the bloc? Thanks!

Cannot add new events after calling close

Hi,

I'm getting this error when trying to call a state method that dispatches an event:

I/flutter (27135): ══║ EXCEPTION CAUGHT BY GESTURE β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
I/flutter (27135): The following StateError was thrown while handling a gesture:
I/flutter (27135): Bad state: Cannot add new events after calling close
I/flutter (27135):
I/flutter (27135): When the exception was thrown, this was the stack:
I/flutter (27135): #1      Subject._add (package:rxdart/src/subjects/subject.dart:124:16)
I/flutter (27135): #2      Subject.add (package:rxdart/src/subjects/subject.dart:118:5)
I/flutter (27135): #3      _StreamSinkWrapper.add (package:rxdart/src/subjects/subject.dart:150:13)
I/flutter (27135): #4      Bloc.dispatch (package:bloc/src/bloc.dart:27:24)
I/flutter (27135): #5      AuthenticationBloc.onLoginButtonPressed (package:eat_app/blocs/authentication_bloc.dart:141:5)
I/flutter (27135): #6      _AuthPageState._onLoginButtonPressed (package:eat_app/pages/auth_page.dart:177:14)
I/flutter (27135): #7      _AuthPageState._buildLoginPage.<anonymous closure>.<anonymous closure> (package:eat_app/pages/auth_page.dart:157:29)
I/flutter (27135): #8      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
I/flutter (27135): #9      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:562:30)
I/flutter (27135): #10     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
I/flutter (27135): #11     TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
I/flutter (27135): #12     TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:204:7)
I/flutter (27135): #13     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
I/flutter (27135): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:147:20)
I/flutter (27135): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
I/flutter (27135): #16     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
I/flutter (27135): #17     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
I/flutter (27135): #18     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
I/flutter (27135): #19     _invoke1 (dart:ui/hooks.dart:153:13)
I/flutter (27135): #20     _dispatchPointerDataPacket (dart:ui/hooks.dart:107:5)
I/flutter (27135): (elided one frame from package dart:async)
I/flutter (27135):
I/flutter (27135): Handler: onTap
I/flutter (27135): Recognizer:
I/flutter (27135):   TapGestureRecognizer#5dc3e(debugOwner: GestureDetector, state: ready, won arena, finalPosition:
I/flutter (27135):   Offset(269.7, 428.6), sent tap down)
I/flutter (27135): ════════════════════════════════════════════════════════════════════════════════════════════════════

The function is being called here:

    authBloc.onLoginButtonPressed(
        email: _loginEmailTextEditingController.text,
        password: _loginPasswordTextEditingController.text);

And the function that calls the dispatch is:

void onLoginButtonPressed({@required String email, @required String password}) {
    dispatch(
      LoginButtonPressed(email: email, password: password )
    );
  }

listen to state out of build

i have a question

i want listen to state, and doing something with new state
for example i want listen to AuthenticationState, when is AuthenticationAuthenticated i want after 3 seconds push to new page, how can achieve to this ?

thanks

Can BlocBuilder be used with multiple blocs?

Using flutter_bloc 0.5.2

At the top level of my app I have a custom BlocProvider which is very similar to yours, but gives me access to two of my blocs (i) AppDataBloc (ii) AnalyticsBloc.

My view is wrapped in your BlockBuilder and it passes in the main AppDataBloc bloc as the bloc parameter.

Inside my view it uses AppDataBloc to load initial data and on scrolling (infinite scroll). Other actions on that page may cause an event for AnalyticsBloc to be dispatched.

This seems to work most of the time, but I have noticed that some of the AnalyticsBloc events get delayed until some other action is performed e.g. AnalyticsBloc::mapEventToState isn't executed until I change to a different view or trigger the infinite scroll on the main view.

Looking in the debugger I can see that all events have been correctly dispatched and that the processing is delayed.

Is this because the BlockBuilder only knows about the stream from AppDataBloc and so it doesn't cause a flutter render when AppDataBloc is changed? This was my initial thought, but it doesn't explain why it frequently works.

Should I be using two different blocs like this? Should I be able to dispatch an event to any other unrelated bloc from inside BlockBuilder?

Help needed (BlocBuilder builder method executes with state == null.)

Hi!

I am trying to trigger an event that in turn makes a network REST call, and finally, render a widget injected by the response data.

I am trying to dispatch my event in the build() method of an extended State class of a StatefulWidget.

  1. My BlocBuilder builder method executes right away with a state == null.
  2. Then my mapEventToState is executed, make the network call, get the results back, everything is fine.
  3. My BlocBuilder builder never gets executed again...

I tried to mimic the flutter github search structure. Any idea on what I am missing?

Thanks!

How to provide Multiple Blocs using BlocProvider?

I have to provide multiple blocs to application level.

    final withAuth = BlocProvider<AuthenticationBloc>(
      bloc: _authenticationBloc,
      child: app,
    );

    return BlocProvider<NotificationBloc>(
      bloc: _notificationBloc,
      child: withAuth,
    );

Are there any cleaner solutions?

Are you confident the BlocProvider will work as intended?

Looking at the BlocProvider code I found that you are using the BuildContext.ancestorWidgetOfExactType method instead of
BuildContext.inheritFromWidgetOfExactType
From what I could gather this will prevent Widgets that use the BlocProvider from rebuilding when the Bloc is swapped for another one.
I have already created a version that derives BlocProvider from StatelessWidget because I don't need the addditional overhead that comes with using InheritedWidget.
I haven't made a pull request so far as I have no time to make the required tests to support my claim. Let me know if you are interested.

Delay when dispatching event

i wrote an example of github search api (similar to your example provided) just to get familiar with the idea of bloc and i found that when events are sent in delays which leads to inconstant behaviour.
here is my implementation of the bloc class


class SearchEvent {}

class SearchState {}

class SubmitSearchEvent implements SearchEvent {
  String query;
  SubmitSearchEvent({this.query});
}

class SearchEmptyState implements SearchState {}

class SearchLoadingState implements SearchState {}

class SearchSuccessState implements SearchState {
  final SearchResult result;
  SearchSuccessState(this.result);
}

class SearchErrorState implements SearchState {
  final Error error;

  SearchErrorState(this.error);
}

class SearchBloc extends Bloc<SearchEvent, SearchState> {
  final SearchApi _api;
  SearchBloc(this._api);
  @override
  SearchState get initialState => SearchEmptyState();
  @override
  void onTransition(Transition<SearchEvent, SearchState> transition) {
    super.onTransition(transition);
    print("${DateTime.now()} ");
    print("event: ${transition.event}");
    print("current state: ${transition.currentState}");
    print("next state: ${transition.nextState}");
  }

  @override
  Stream<SearchState> mapEventToState(
      SearchState currentState, SearchEvent event) async* {
    if (event is SubmitSearchEvent) {
      var query = event.query;
      if (query.isEmpty)
        yield SearchEmptyState();
      else {
        yield SearchLoadingState();
        try {
          var response = await _api.queryRepositores(query);
          yield SearchSuccessState(response);
        } catch (error) {
          yield SearchErrorState(error);
        }
      }
    }
  }

  @override
  void dispose() {
    super.dispose();
  }
}

here the ui implementation

void main() => runApp(MaterialApp(
      home: Main(),
      theme: ThemeData(),
    ));

class Main extends StatefulWidget {
  @override
  _MainState createState() => _MainState();
}

class _MainState extends State<Main> {
  String value = "";

  SearchBloc _searchBloc;
  @override
  void initState() {
    _searchBloc = SearchBloc(SearchApi());
    super.initState();
  }

  @override
  void dispose() {
    _searchBloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('text'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              children: <Widget>[
                TextField(
                  onChanged: (newValue) {
                    _searchBloc.dispatch(SubmitSearchEvent(query: newValue));
                  },
                  decoration: InputDecoration(
                      border: UnderlineInputBorder(
                          borderRadius: BorderRadius.all(Radius.circular(10))),
                      prefixIcon: Icon(Icons.search),
                      filled: true,
                      hintText: 'Search for Repositories'),
                ),
              ],
            ),
          ),
          BlocBuilder(
            bloc: _searchBloc,
            builder: (context, event) {
              if (event is SearchLoadingState) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else if (event is SearchEmptyState) {
                return Center(child: Text('Search for data'));
              } else if (event is SearchSuccessState) {
                return Center(
                  child: Text("Success ${event.result.totalCount}"),
                );
              } else if (event is SearchErrorState) {
                return Center(child: Text(event.error.toString()));
              } else {
                return Center(child: Text('Search for data'));
              }
            },
          )
        ],
      ),
    );
  }
}

and here is the log with timestamp between each event

I/flutter ( 1846): 2019-01-28 17:24:35.854326
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchEmptyState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=s
I/flutter ( 1846): 2019-01-28 17:24:38.570055
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState
I/flutter ( 1846): 2019-01-28 17:24:38.570929
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchSuccessState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=se
I/flutter ( 1846): 2019-01-28 17:24:39.593691
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState
I/flutter ( 1846): 2019-01-28 17:24:39.594166
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchSuccessState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=sea
I/flutter ( 1846): 2019-01-28 17:24:40.484570
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState
I/flutter ( 1846): 2019-01-28 17:24:40.485276
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchSuccessState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=sear
I/flutter ( 1846): 2019-01-28 17:24:41.964403
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState
I/flutter ( 1846): 2019-01-28 17:24:41.964978
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchSuccessState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=searc
I/flutter ( 1846): 2019-01-28 17:24:43.177989
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState
I/flutter ( 1846): 2019-01-28 17:24:43.179184
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchSuccessState - next state: SearchLoadingState
I/flutter ( 1846): sending request to https://api.github.com/search/repositories?q=search
I/flutter ( 1846): 2019-01-28 17:24:44.129876
I/flutter ( 1846): event: SubmitSearchEvent - current state: SearchLoadingState - next state: SearchSuccessState

idk if im doing something wrong but everything seems to be ok.
thanks for the library and your time.

[Question] How would you manage animation in the bloc builder?

Hi all, Thanks for this component. Looks very promising.

I'm struggling with a question. How would you manage animation and controller in the Bloc builder?

Image that on the login example you would have a PageView instead of a stack with the Splash as first page and the Login/Home as second page. When the initialization completes you want to use a page controller to animate from the Splash page to the Home/Login page.

How would you do that?

Thanks,

Alex.

mapEventToState not called if dispatched events quickly

Just wondering if anyone has run into an issue where calling dispatch multiple times in quick succession results in mapEventToState not being called?

I have a listener on a socket and when it gets fired, it does _messageBloc.dispatch(MessageReceived(name: name, body: body));

I can print the contents of the message in the listener, but my print statement in mapEventToState only usually gets called for the last message.

If I send a single message after waiting, it makes it to mapEventToState every time.

No exceptions are thrown, I'm on the latest versions of everything.

If you need more info, let me know.

The currentEvent variable is not updated in time

Describe the bug
In the _bindStateSubject function of the "bloc/packages/bloc/lib/src/bloc.dart" file,
The currentEvent variable is not updated in time.

modify the lines
"
65 (S nextState) {
66 final transition = Transition(
"
to

"
65 (S nextState) {
66 currentState = _stateSubject.value;
67 final transition = Transition(
"
Because of each foreach loop, the value of the currentState variable will change.

BlocBuilder provides initial state instead of actual state.

Describe the bug
It seems that BlocBuilder is not showing actual state, but an initial one. State in the app is managed correctly, and Bloc is provided to the Widget.

To Reproduce
You can reproduce the error by trying to use BlocBuilder in widget, where you provide Bloc with BlocProvider.of(context); It seems that problem is happening only in this case. Does the same on login flow example, if you try using BlocBuilder in home_page.dart

Expected behavior
I expect to get actual state instead of initial one.

Code
main.dart BlocBuilder works with authBloc, profile_page.dart BlocBuilder does not work, but StreamBuilder works. This leads me to believe, that Bloc is provided correctly. onPressed events also work.

main.dart

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:testapp/authentication/authentication.dart';
import 'package:testapp/pages/drawer/test_page.dart';
import 'package:testapp/pages/login/forgot_page.dart';
import 'package:testapp/pages/home_page.dart';
import 'package:testapp/pages/login/login_page.dart';
import 'package:testapp/pages/drawer/profile_page.dart';
import 'package:testapp/pages/login/signup_page.dart';
import 'package:testapp/pages/login/splash_page.dart';
import 'package:testapp/widgets/loading_indicator.dart';

class SimpleBlocDelegate extends BlocDelegate {
  @override
  void onTransition(Transition transition) {
    print(transition.toString());
  }
}

void main() {
  BlocSupervisor().delegate = SimpleBlocDelegate();
  runApp(App());
}

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  final AuthenticationBloc _authBloc = AuthenticationBloc();

  _AppState() {
    _authBloc.onAppStart();
  }

  @override
  void dispose() {
    _authBloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      bloc: _authBloc,
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'LastMile',
        theme:
        // ThemeData.dark(),
        ThemeData(
          primarySwatch: Colors.orange,
        ),
        routes: <String, WidgetBuilder>{
          '/home': (context) => HomePage(),
          '/login': (context) => LoginPage(),
          '/signup': (context) => SignupPage(),
          '/forgot': (context) => ForgotPage(),
          '/profile': (context) => ProfilePage(),
          '/test': (context) => TestPage(),
        },
        home: _rootPage(),
      ),
    );
  }

  Widget _rootPage() {
    return BlocBuilder<AuthenticationEvent, AuthenticationState>(
      bloc: _authBloc,
      builder: (BuildContext context, AuthenticationState state) {
        List<Widget> widgets = [];

        if (state.isAuthenticated) {
          widgets.add(HomePage());
        } else {
          widgets.add(LoginPage());
        }

        if (state.isInitializing) {
          widgets.add(SplashPage());
        }

        if (state.isLoading) {
          widgets.add(LoadingIndicator());
        }

        return Stack(
          children: widgets,
        );
      },
    );
  }

}

profile_page.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:testapp/authentication/authentication.dart';

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final AuthenticationBloc _authBloc =
        BlocProvider.of<AuthenticationBloc>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Profile')),
      body: Center(
        child: Column(children: <Widget>[
          BlocBuilder<AuthenticationEvent, AuthenticationState>(
            bloc: _authBloc,
            builder: (BuildContext context, AuthenticationState state) {
              if (state.isAuthenticated) {
                return Text('User ID: ${state.userId}');
              } else {
                return Text('Loading data');
              }
            },
          ),
          StreamBuilder(
            stream: _authBloc.state,
            initialData: _authBloc.initialState,
            builder: (context, AsyncSnapshot<AuthenticationState> state) {
              if (state.data.isAuthenticated) {
                return Text('User ID: ${state.data.userId}');
              } else {
                return Text('Loading data');
              }
            },
          ),
          RaisedButton(
            child: Text('Link Facebook'),
            onPressed: _authBloc.onLinkFacebookButtonPressed,
          ),
          RaisedButton(
            child: Text('Link Google'),
            onPressed: _authBloc.onLinkGoogleButtonPressed,
          ),
          RaisedButton(
            child: Text('Sign out'),
            onPressed: () {
              _authBloc.onLogout();
              Navigator.pop(context);
            },
          ),
          RaisedButton(
            child: Text('Delete user'),
            onPressed: () {
              Navigator.pop(context);
              _authBloc.onDeleteUser();
            },
          ),
        ]),
      ),
    );
  }
}

screenshot 2018-12-10 at 18 09 18

**Logs **
flutter analyze:
No issues found! (ran in 3.2s)

flutter doctor -v:
[βœ“] Flutter (Channel beta, v1.0.0, on Mac OS X 10.14.1 18B75, locale en-LT)
β€’ Flutter version 1.0.0 at /Users/algirdas/development/flutter
β€’ Framework revision 5391447fae (11 days ago), 2018-11-29 19:41:26 -0800
β€’ Engine revision 7375a0f414
β€’ Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[βœ“] Android toolchain - develop for Android devices (Android SDK 28.0.3)
β€’ Android SDK at /Users/algirdas/Library/Android/sdk
β€’ Android NDK location not configured (optional; useful for native profiling support)
β€’ Platform android-28, build-tools 28.0.3
β€’ ANDROID_HOME = /Users/algirdas/Library/Android/sdk
β€’ Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
β€’ Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
β€’ All Android licenses accepted.

[βœ“] iOS toolchain - develop for iOS devices (Xcode 10.1)
β€’ Xcode at /Applications/Xcode.app/Contents/Developer
β€’ Xcode 10.1, Build version 10B61
β€’ ios-deploy 1.9.4
β€’ CocoaPods version 1.5.3

[βœ“] Android Studio (version 3.2)
β€’ Android Studio at /Applications/Android Studio.app/Contents
β€’ Flutter plugin version 31.1.1
β€’ Dart plugin version 181.5656
β€’ Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)

[βœ“] VS Code (version 1.29.1)
β€’ VS Code at /Applications/Visual Studio Code.app/Contents
β€’ Flutter extension version 2.21.1

[βœ“] Connected device (1 available)
β€’ iPhone XS Max β€’ 3A626DC0-8339-4895-B831-738F98A987DA β€’ ios β€’ iOS 12.1 (simulator)

β€’ No issues found!

Offer a way to execute an action on "initial state"/ when a widget has been loaded

Is your feature request related to a problem? Please describe.
As a user of bloc, I'd like to have a way to identify a WidgetHasBeenLoaded UiEvent. This way, if I need to respond in my bloc to an action immediately after a widget has been drawn on the screen, I can do it without relying on the bloc constructor, which might be too late.
By also following this approach, we would respect the single input/single output, allowing us to still track the events and responses.

Describe the solution you'd like
We might have to alternatives:

  @override
  Stream<SalutationUiState> mapEventToState(
      SalutationUiState state, event) async* {
    if (event is WidgetHasBeenLoaded) {
      // do your job here
    }
  }

where WidgetHasBeenLoaded is a UiEvent provided by Bloc.

Or we could add an additional method, optional, to the bloc API that is just: Future<UiState> onInitialEvent() (or similar).

Describe alternatives you've considered
At this moment, the only way to achieve this is using the bloc's constructor. However, that might be too soon: if you initialize your bloc in an upper node of your tree, but it is only consumed in a widget on lower leafs, we might get the result of the action before even the widget was rendered.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.