Skip to content

Instantly share code, notes, and snippets.

@mosheduminer
Last active July 16, 2021 12:11
Show Gist options
  • Save mosheduminer/0b82f24d53fd846227f1954b07349d76 to your computer and use it in GitHub Desktop.
Save mosheduminer/0b82f24d53fd846227f1954b07349d76 to your computer and use it in GitHub Desktop.
Reactive Flutter
import 'package:flutter/material.dart';
import 'dart:collection';
import 'dart:async';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: DemoWidget(),
),
),
);
}
}
class DemoWidget extends StatelessWidget {
final Signal signal;
DemoWidget() : signal = Signal<int>(0) {
Timer.periodic(Duration(seconds: 1), (timer) {
signal.write(signal.read() +1);
});
}
@override
Widget build(BuildContext context) {
return Reactive(() => Text('Count: ${signal.read()}', style: Theme.of(context).textTheme.headline4));
}
}
final context = List<Subscription>.empty(growable: true);
void subscribe(
Subscription running, LinkedHashSet<Subscription> subscriptions) {
subscriptions.add(running);
running.dependencies.add(subscriptions);
}
void cleanup(Subscription running) {
for (final dep in running.dependencies) {
dep.remove(running);
}
running.dependencies.clear();
}
class Signal<T> {
final LinkedHashSet<Subscription> subscriptions =
LinkedHashSet<Subscription>();
T value;
Signal(this.value);
T read() {
if (context.isNotEmpty) {
final running = context[context.length - 1];
subscribe(running, subscriptions);
}
return value;
}
void write(nextValue) {
value = nextValue;
for (final sub in subscriptions.toList()) {
sub.execute();
}
}
}
class Subscription {
Subscription(this.execute, this.dependencies);
Function execute;
LinkedHashSet<LinkedHashSet<Subscription>> dependencies;
}
class Effect {
final Function fn;
late Subscription running;
Effect(this.fn) {
running =
Subscription(_execute, LinkedHashSet<LinkedHashSet<Subscription>>());
_execute();
}
void _execute() {
cleanup(running);
context.add(running);
try {
fn();
} finally {
context.removeLast();
}
}
}
class Reactive extends StatefulWidget {
final Widget Function() widgetFunction;
const Reactive(this.widgetFunction, {Key? key}) : super(key: key);
@override
State<Reactive> createState() => _ReactiveState();
}
class _ReactiveState extends State<Reactive> {
var firstTime = true;
Widget? results;
@override
void initState() {
super.initState();
Effect(() {
results = widget.widgetFunction();
if (!firstTime) {
setState(() {});
} else {
firstTime = false;
}
});
}
@override
Widget build(BuildContext context) {
return results!;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment