Closed milansurelia closed 3 months ago
I would suggest Provider, lite_ref(my package) or something that hooks into the lifecycle of widgets because signals are disposable and GetIt wouldn't know when to dispose them. Therefore, using GetIt for disposables doesn't make much sense unless it's for long-lived signals (eg. Apptheme).
Provider/lite_ref also allow easy mocking.
In the example below, the Controller
will be disposed when CounterText
is unmounted. You can't achieve this with GetIt.
class Controller {
late final _count = signal(0);
// we expose it as a readonly
// so it cannot be changed from outside the controller.
ReadonlySignal<int> get count => _count;
void increment() => _count.value++;
void decrement() => _count.value--;
void dispose() {
_count.dispose()
}
}
final countControllerRef = Ref.scoped((ctx) => Controller());
class CounterText extends StatelessWidget {
const CounterText({super.key});
@override
Widget build(BuildContext context) {
final controller = countControllerRef.of(context);
final count = controller.count.watch(context);
return Text('$count');
}
}
In my signals package (state_beacon). I created a BeaconController
that disposes all beacons created in it; as well as a select
extension method that makes watching beacons more ergonomic. Rody could do the same for signals. This is how the code would look:
class Controller extends BeaconController {
late final _count = B.writable(0);
// we expose it as a readable beacon
// so it cannot be changed from outside the controller.
ReadableBeacon<int> get count => _count;
void increment() => _count.value++;
void decrement() => _count.value--;
}
final countControllerRef = Ref.scoped((ctx) => Controller());
class CounterText extends StatelessWidget {
const CounterText({super.key});
@override
Widget build(BuildContext context) {
final count = countControllerRef.select(context, (c) => c.count);
return Text('$count');
}
}
Description This issue aims to discuss the best approach for dependency injection of the signal service class within the signals library. Currently, there's no clear guidance on whether to use Provider or GetIt.
Context:
We want to decouple the signal service class from dependent components. We need a mechanism to inject the signal service dependency. Possible Solutions:
Provider:
Pros: Widely adopted in the Flutter community. Offers good integration with the widget lifecycle. Provides features like change notifications.
Cons: Might introduce additional complexity for non-widget contexts.
GetIt:
Pros: Simple and lightweight service locator pattern. Easier to access dependencies from anywhere in the app (including non-widget contexts). Supports mocking for easier testing.
Cons: Less familiar to developers coming from other frameworks. Might lead to tighter coupling if not used carefully.
Discussion Points:
Which approach aligns better with the overall design philosophy of the signals library? Are there any specific use cases that favor one option over the other? Should the library provide guidance or examples for both approaches?
Additional Information:
I hope this discussion helps us determine the best way to handle dependency injection for the signal service class. Let's share our thoughts and experiences!