Describe the bug
I migrated the library in one of my projects from 3.0.0 to 6.0.0 and a weird behaviour started. I'm listening to a bloc from other blocs this way:
final GameBloc gameBloc;
StreamSubscription gameBlocSubscription;
BoardBloc(this.gameBloc) : super(BoardState()){
gameBlocSubscription = gameBloc.listen((state) {
if(state is GameStarted){
...
}
if(state is GameContinued){
...
}
});
}
This was working properly before, but after the migration the first time I change the state of the game bloc, the listeners don't capture the change of state, however if I go back and redo the event (on the same session) then it works fine, so it only happens that the event does not get listened the first time.
Was there any breaking changes on how this was intended to work?
To Reproduce
Steps to reproduce the behavior:
I don't have a sample project, but simple listening to a bloc's change of state from another bloc
Expected behavior
Expect the receiving bloc to listen to the change of state the first time is triggered
Paste the output of running flutter doctor -v
here.
[✓] Flutter (Channel master, 1.22.0-10.0.pre.45, on Mac OS X 10.15.4 19E287, locale en-CA)
• Flutter version 1.22.0-10.0.pre.45 at /Users/josegeorges/Desktop/development/flutter
• Framework revision cb819504f3 (3 weeks ago), 2020-09-02 12:31:17 -0700
• Engine revision 165abef0a2
• Dart version 2.10.0 (build 2.10.0-77.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/josegeorges/Library/Android/sdk
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.5, Build version 11E608c
• CocoaPods version 1.9.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 48.1.2
• Dart plugin version 193.7547
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] VS Code (version 1.48.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.13.2
[✓] Connected device (4 available)
• Pixel 3 XL (mobile) • 8BQY12FAC • android-arm64 • Android 10 (API 29)
• macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E287
• Web Server (web) • web-server • web-javascript • Flutter Tools
• Chrome (web) • chrome • web-javascript • Google Chrome 85.0.4183.102
• No issues found!
EDIT
I noticed many issues were opened regarding this and the change is documented in the docs, but what would be the suggestion to modify this behaviour to have it the way it was intended in the first place, if I'm already depending in something like this throughout most of the app?
Hey @JoseGeorges8 👋
Thanks for opening an issue!
As you noticed, this was an intentional breaking change made in v6.0.0 and is documented in the migration guide.
I would recommend:
_onGameStateChange(gameBloc.state);
gameBlocSubscription = gameBloc.listen(_onGameStateChange);
void _onGameStateChange(GameState state) {
if(state is GameStarted){
...
}
if(state is GameContinued){
...
}
}
Hope that helps and sorry for any inconvenience!
Am having a similar issue and I have changed my code (as per your suggestion) as follows:
class StatBloc extends Bloc<StatEvent, StatState> {
StreamSubscription taskSubscription;
StatBloc({TaskBloc taskBloc})
: assert(taskBloc != null),
super(StatsLoading()) {
void _onTaskStateChange(TaskState state) {
print('I am listening for task state changes');
if (state is TasksLoaded) {
add(StatsUpdated(state.tasks));
}
}
taskSubscription = taskBloc.listen(_onTaskStateChange);
}
And nothing is being called. Any ideas please?
It's essentially the same stats bloc from ToDos example where I notice the same behaviour, the stats bloc is always loading until I interact with a task.
Hey, you forgot to call the callback with the current state of the Bloc, the first line of Felix's snippet 👍
class StatBloc extends Bloc<StatEvent, StatState> {
StreamSubscription taskSubscription;
StatBloc({TaskBloc taskBloc})
: assert(taskBloc != null),
super(StatsLoading()) {
void _onTaskStateChange(TaskState state) {
print('I am listening for task state changes');
if (state is TasksLoaded) {
add(StatsUpdated(state.tasks));
}
}
// Update with current Task Bloc state.
_onTaskStateChange(taskBloc.state);
taskSubscription = taskBloc.listen(_onTaskStateChange);
}
// ...
}
@Jomik you hero thank you!
Hm, I'm having the exact same 'issue'.
I'm using AngularDart, where I do a lot of:
<div>{{(counterBloc | async).count</div>
These don't work anymore, unless if I would do:
void ngOnInit() {counterBloc.add(CountEvent(count: 1))}
CounterBloc() : super(0);
I'm sure it makes sense, but I guess I'm missing something here :)
@dotdotcommadot the value passed to super is the initial value of the bloc so you shouldn't need to add an event in ngOnInit
.
Closing for now since that is unrelated to the original issue. And as always, thanks @Jomik for your help! 💯
Thanks for the help!
Most helpful comment
Thanks for the help!