Skip to content

Instantly share code, notes, and snippets.

@felangel
Created May 2, 2019 02:38
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felangel/d9322837c07721b97ae2f7be541cabb2 to your computer and use it in GitHub Desktop.
Save felangel/d9322837c07721b97ae2f7be541cabb2 to your computer and use it in GitHub Desktop.
flutter_bloc with flutter_hooks
import 'package:flutter/material.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
enum CounterEvent { increment, decrement }
class CounterBloc extends Bloc<CounterEvent, int> {
@override
int get initialState => 0;
@override
Stream<int> mapEventToState(
CounterEvent event,
) async* {
switch (event) {
case CounterEvent.increment:
yield currentState + 1;
break;
case CounterEvent.decrement:
yield currentState - 1;
break;
}
}
}
main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => MyPage(),
'/details': (context) => MyDetailsPage(),
},
initialRoute: '/',
);
}
}
class MyPage extends HookWidget {
@override
Widget build(BuildContext context) {
final _counterBloc = useBloc(() => CounterBloc());
return Scaffold(
appBar: AppBar(
title: Text('Bloc Hook'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.navigate_next),
onPressed: () {
Navigator.of(context).pushReplacementNamed('/details');
},
)
],
),
body: BlocBuilder<CounterEvent, int>(
bloc: _counterBloc,
builder: (BuildContext context, int count) {
return Center(
child: Text(
'$count',
style: TextStyle(fontSize: 24.0),
),
);
},
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_counterBloc.dispatch(CounterEvent.increment);
},
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: Icon(Icons.remove),
onPressed: () {
_counterBloc.dispatch(CounterEvent.decrement);
},
),
),
],
),
);
}
}
class MyDetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: RaisedButton(
child: Text('Go Back'),
onPressed: () {
Navigator.of(context).pushReplacementNamed('/');
},
),
),
);
}
}
T useBloc<T extends Bloc>(T Function() blocFactory,
[List<Object> keys = const <dynamic>[]]) {
return Hook.use(_BlocHook(
blocFactory,
keys: keys,
));
}
class _BlocHook<T extends Bloc> extends Hook<T> {
final T Function() blocFactory;
const _BlocHook(
this.blocFactory, {
List<Object> keys = const <dynamic>[],
}) : assert(blocFactory != null),
assert(keys != null),
super(keys: keys);
@override
_BlocHookState<T> createState() => _BlocHookState<T>();
}
class _BlocHookState<T extends Bloc> extends HookState<T, _BlocHook<T>> {
T bloc;
@override
void initHook() {
super.initHook();
bloc = hook.blocFactory();
}
@override
T build(BuildContext context) {
return bloc;
}
@override
void dispose() {
bloc.dispose();
super.dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment