Skip to content

Instantly share code, notes, and snippets.

@Aidanvii7
Last active July 9, 2019 16:31
Show Gist options
  • Save Aidanvii7/9ef85b64844b05946e165cd1d3f025e2 to your computer and use it in GitHub Desktop.
Save Aidanvii7/9ef85b64844b05946e165cd1d3f025e2 to your computer and use it in GitHub Desktop.
A convenience widget for providing instances of Store, with automatic disposal
import 'package:flutter/widgets.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart';
typedef ConsumerObserverBuilder<T> = Widget Function(BuildContext context, T value);
class ConsumerObserver<T> extends StatelessWidget {
final ConsumerObserverBuilder<T> builder;
final Widget prebuiltChild;
ConsumerObserver({
Key key,
@required this.builder,
this.prebuiltChild
})
: assert(builder != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Consumer(
child: prebuiltChild,
builder: (context, T value, Widget child) {
return Observer(
builder: (context) => builder(context, value) ?? child ?? Container(width: 0, height: 0),
);
},
);
}
}
class ReactOn<T> extends ConsumerObserver<T> {
ReactOn(Widget Function(T value) builder, { Widget prebuiltChild })
:
assert(builder != null),
super(builder: (context, value) => builder(value), prebuiltChild: prebuiltChild);
ReactOn.withContext(Widget Function(T value, BuildContext context) builder, { Widget prebuiltChild })
:
assert(builder != null),
super(builder: (context, value) => builder(value, context), prebuiltChild: prebuiltChild);
}
// sample usage:
class CounterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StoreProvider(
storeBuilder: (_) => CounterStore(),
child: _CounterApp(),
);
}
}
class _CounterApp extends StatelessWidget {
CounterStore _counterStore(final BuildContext context) => Provider.of<CounterStore>(context);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Counter example'),
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
_counterStore(context).reset();
},
)
],
),
),
body: Center(
child: Column(
children: <Widget>[
ReactOn<CounterStore>((store) {
return Text("You tapped the floating action button ${store.counter1} times!");
}),
ReactOn<CounterStore>((store) {
return MaterialButton(
child: Text("You tapped this ${store.counter2} times!"),
onPressed: () {
store.increment2();
},
);
}),
ReactOn<CounterStore>((store) {
return Text("Counter sum is ${store.counterSum}");
})
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_counterStore(context).increment1();
},
),
),
);
}
}
import 'package:mobx/mobx.dart';
part 'counter_store.g.dart';
class CounterStore = _CounterStore with _$CounterStore;
abstract class _CounterStore with Store {
@observable
int counter1 = 0;
@observable
int counter2 = 0;
@computed
int get counterSum => counter1 + counter2;
@action
void increment1() {
counter1++;
}
@action
void increment2() {
counter2++;
}
@action
void reset() {
counter1 = 0;
counter2 = 0;
}
}
import 'package:flutter/widgets.dart';
import 'package:mobx/mobx.dart';
import 'package:provider/provider.dart';
typedef StoreBuilder<T extends Store> = T Function(BuildContext context);
class StoreProvider<T extends Store> extends StatelessWidget {
StoreBuilder<T> _storeBuilder;
final Widget child;
StoreProvider({
Key key,
@required StoreBuilder<T> storeBuilder,
this.child
})
: assert(storeBuilder != null),
super(key: key) {
_storeBuilder = storeBuilder;
}
@override
Widget build(BuildContext context) {
return Provider<T>(
builder: _storeBuilder,
dispose: (_, store) => store.dispose(),
child: child,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment