My take on bringing the Widget to the Stateful.
- Basically uses StatefulWidgets as
Controllerto store your logic, moving thebuild(BuildContext)to the Widget part.
StateWidget: Widget to use instead of StatefulWidget.
StateController: "stateful" class to use instead of State
ParentStateWidget<StateController> (or the mixin on StatelessWidget ParentStateMixin<StateController>)
to inherit a "state" from a parent StateController.
-
Provides a basic dependency injection with
Bucket. -
Has a
NotifierValue<T>, a glorified reactive ValueNotifier. That works withObserver()andObserverBuilder()widgets. -
Makes heavy usage of extensions on
BuildContext. To dispatch notifications, you can usecontext.notifyData()and capture it up in the tree withNotificationListener()
Install with:
dependencies:
jasn:
git: https://github.com/roipeker/jasn.gitCreate Bucket:
final bucket = Bucket();
or use the singleton Bucket.instance
Inject an instance:
bucket.put(MyService());Lazy initialization (creates instance when its retrieved).
bucket.lazyPut(()=>MyService());Factory instance generation (creates a new instance each time is retrieved)
bucket.factory(()=>MyService());Retrieve an Instance:
final MyService service = bucket.get();
// or callable version
bucket<MyService>();Remove an instance:
bucket.delete<MyService>();Reset all instances:
bucket.reset();Check if it exists:
bucket.exists<MyService>()class HomePage extends StateWidget<HomePageState> {
const HomePage({Key? key}) : super(key: key);
@override
createState() => HomePageState();
/// Like an StatefulWidget but `build()` comes here.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: HomeMenu(),
);
}
}
/// The State is a `StateController`
class HomePageState extends StateController<HomePage> {
late final name = 'Nick'.obs();
late final switcher = false.obs(onChange: onSwitchChange);
String get someUserName => bucket<SomeService>().username;
@override
void dispose() {
name.dispose();
switcher.dispose();
super.dispose();
}
void onChangeNamePress() {
name.value += 'o';
}
}
/// A Stateless widget... that searches for a parent StateController
class HomeMenu extends ParentStateWidget<HomePageState> {
const HomeMenu({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
/// you can "subscribe" to `NotifierValue` (.obs) as if it where InheritedWidgets.
/// This Stateless will rebuild when `switcher` changes.
final value = context.listen(state.switcher);
return Column(
children:[
Observer(() => Text(state.name)),
Observer(() => Text("switch is: $value")),
]);
}
}
Is just a playful idea to stay purist on Flutter.