Bloc: [Bug] + [Design Question] Bloc per widget instance?

Created on 22 Jun 2019  路  8Comments  路  Source: felangel/bloc

Use case:

I have a user widget (route), that gets a user id and display it (or a loading indicator while loading, or an error if there's an error). Also, I'm using transitions between routes.

Currently, I'm using a single 'user bloc', with state Empty,Loading,Done, and Error.
When user page starts, if state is empty it will load. if state is Done it will compare the user id with the state user id, and if different, will load as well.

The problem happens when I'm routing from a user page with id='userA' to another user page with id='userB'. At the beginning, both pages are shown (old one transitioning out, new one transitioning in), and at that point both of them share the same bloc. However, I want the old page to show the old user, and the new one to show a loading indicator (or the new user if it's fast enough).

What's the recommended way to achieve that?

question

All 8 comments

Hi @matanshukry 馃憢
Thanks for opening an issue!

Can you please provide a link to your current implementation? It would be much easier for me to understand and give feedback/suggestions if I'm able to look at the code and run the app locally.

Thanks! 馃憤

Closing for now but feel free to comment with additional details and I'm happy to continue the conversation 馃憤

I can't actually, it's a private and a really big one.
But I'll try to create a simple one tomorrow or the day after

Sounds good!

Example is ready: https://github.com/matanshukry/bloc_ex

After running the app, press on 'Page A': You should see the page transitioning in from the left (sliding transition), with a circular progress bar (really big and weird, but w/e).

Then press on "Go to user bar". You can see the same thing happening, but:
The page that is supposed to "leave" (no transition), now has a circular progress bar as well. I want them to be separate, so while the other user is loaded from the left, the current user state should not be changed.

p.s.
The example also shows a bug with BlocListener, where it will be called twice even though the transition and the event were executed once and correctly.

Hi @matanshukry thanks for putting that together!

I created a PR to try to address your concerns. I think the problem was you had a single global instance of UserBloc instead of an instance per page.

Let me know if the PR addressed your concerns or if you still have questions. Also, I wasn't able to see the bug with BlocListener. Let me know if it's still a concern and I'm happy to continue to investigate it 馃憤

@felangel Awesome! that is exactly what I was looking for; an "instance per page".
One issue regarding implementation though:

You used the bloc provider outside of the widget it self (outside of the UserPage). I tried to add it inside, but then the problem is with BlocProvider.of<UserBloc>(context);. Since the code is running in the same scope as the BlocProvider, the context doesn't contain the bloc yet, and this throws an exception.

  1. I might be looking at this the wrong way; Is it necessary for the BlocProvider to be outside of the UserPage for some reason? If so, why?
  2. If not, is there a way to use both in the same widget?

@matanshukry that's because recently BlocProvider was updated to automatically dispose the bloc which makes it a StatefulWidget. As a result, the builder doesn't execute until later (when initState is called) so you need to make sure the BlocProvider builds the provided bloc before it's accessed.

You can think of it like normal DI. Since the UserPage needs the UserBloc, it must be given to the UserPage before the page is created. Let me know if that makes sense and great question 馃憤

Was this page helpful?
0 / 5 - 0 ratings