I have some separated view class as App
and MainPage
and i implemented simple Bloc
pattern to handle click event on some widgets such as button and another problem is when i run application i get message in console without click on widgets :|
after running application my implemented bloc pattern only work once and show message in console and after click again that don't work to show message
my main.dart
class
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: Strings.appName,
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: App(),
));
}
class App extends StatefulWidget {
final HomeBloc homeBloc = HomeBloc();
@override
State<App> createState() => MainPage();
}
MainPage
class:
class MainPage extends State<App> {
@override
void initState() {
super.initState();
}
HomeBloc get _homeBloc => widget.homeBloc;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: Strings.appName,
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: BlocBuilder<HomeEvent,HomeState>(
bloc: _homeBloc,
builder: (BuildContext context, HomeState state) {
if (state is HandleDrawerMenuClick) {
_onWidgetDidBuild(() {
print("clicked on drawer menu");
});
}
return Scaffold(
body: Center(
child: RaisedButton(
child: Text('ddddddddd'),
onPressed: () {
_homeBloc.dispatch(OnDrawerMenuClicked());
},
),
),
);
}),
);
}
@override
void dispose() {
_homeBloc.dispose();
super.dispose();
}
void _onWidgetDidBuild(Function callback) {
WidgetsBinding.instance.addPostFrameCallback((_) {
callback();
});
}
}
HomeBloc
class:
class HomeBloc extends Bloc<HomeEvent, HomeState> {
@override
HomeState get initialState => HomeState();
@override
Stream<HomeState> mapEventToState(HomeEvent event) async* {
if (event is OnDrawerMenuClicked) {
yield HandleDrawerMenuClick();
}
}
}
HomeEvent
class:
class HomeEvent extends Equatable {
HomeEvent([List props = const []]) : super(props);
}
class OnDrawerMenuClicked extends HomeEvent {
OnDrawerMenuClicked() : super([]);
@override
String toString() => 'OnDrawerMenuClicked clicked';
}
HomeState
class:
class HomeState extends Equatable{
HomeState([List props = const[]]):super(props);
}
class HandleDrawerMenuClick extends HomeState{
@override
String toString()=>'HandleDrawerMenuClick';
}
i think problem is on HandleDrawerMenuClick
class because when i debug application, debug can go into if
statement on this line:
if (event is OnDrawerMenuClicked) {
yield HandleDrawerMenuClick();
}
and i think twice click on button couldn't trigger yield HandleDrawerMenuClick();
Hi @MahdiPishguy 馃憢
Thanks for opening an issue.
This is because once you click on the button once, the event is dispatched and you yield HandleDrawerMenuClick. Then if you dispatch again, the state is already HandleDrawerMenuClick. If you want it to trigger every time even though the state hasn鈥檛 changed you should not extend Equatable. Also you should use BlocListener to handle the DrawerMenuClick instead of doing it in BlocBuilder.
Check out the snack bar recipe for an example of how and why to use BlocListener.
Hope that helps! 馃憤
@felangel thanks
i'm trying to implementing simple your login project and i need to have BlocBuilder
without using Authentication implementation
No problem!
That鈥檚 fine but just make sure BlocBuilder is only used to return widgets based on states. Any other code like navigation, showing a dialog, etc... doesn鈥檛 belong in BlocBuilder and should be done in BlocListener instead.
Most helpful comment
No problem!
That鈥檚 fine but just make sure BlocBuilder is only used to return widgets based on states. Any other code like navigation, showing a dialog, etc... doesn鈥檛 belong in BlocBuilder and should be done in BlocListener instead.