Hot reload with `SignalProvider` causes create to rerun again
to reproduce use any example use of SignalProvider
i.e https://dartsignals.dev/flutter/signal-provider/
as the title says it's so self explainatory
however in this example
class Counter extends FlutterSignal<int> {
Counter([super.value = 0]);
void increment() => value++;
}
class Example extends StatelessWidget {
const Example({super.key});
@override
Widget build(BuildContext context) {
return SignalProvider<Counter>(
create: () => Counter(),
child: Scaffold(...)
);
}
the create function always creates a new instance of the Counter object causing a new signal to be created every time ! after long trials the only thing i managed to do is to store it in a variable
class Counter extends FlutterSignal<int> {
Counter([super.value = 0]);
void increment() => value++;
}
final counter = Counter();
class Example extends StatelessWidget {
const Example({super.key});
@override
Widget build(BuildContext context) {
return SignalProvider<Counter>(
create: () => counter,
child: Scaffold(...)
);
}
this prevents the behavior but trials to be done to find other unexpected behaviours for the lifecycle
after trial
having autoDispose = true will cause it to throw signal has been read after disposed and will not allow it to recreate it again
after second trial
i used get_it as a service locator to create instances
i'm currently trying to create a good architecture plan using signals with SignalProvider and now got into two usecases
1. singletons (manual lifecycle autoDispose = false)
good for listing pages and long running screens with active services or etc.. using
registerLazySingletonorregisterSingletonand passing the disposeFunc
sl.registerLazySingleton(
() => ProductListingSignal(),
dispose: (signal) => signal.dispose(),
);
usage in screen
SignalProvider<ProductListingSignal>(
create: () => sl(),
child: Scaffold(...)
);
2. factory transient instance (automatic lifecycle autoDispose = true)
good for new pages and pages with parameters using
registerCachedFactoryParaminstead ofregisterFactoryParambecause it would hold a weak ref. and prevent the hot reload bug
sl.registerCachedFactoryParam<ProductDetailsSignal, int, void>(
(i, _) => ProductDetailsSignal(i),
);
usage in screen
SignalProvider<ProductDetailsSignal>(
create: () => sl(param1: index),
child: Scaffold(...)
);
Still looking into the best way to solve for keeping the instances stable on hot reload.
Currently the create callback is treaded like a computed signal so it would get recreated if signals referenced at creation changed.
Hot reload rebuilds computed because of some edge cases in the Watch widget and disposed signals.
i used InhertedProvider from package:provider
check my fork : https://github.com/SPiercer/signals.dart/
I'd also be interested in a solution to this, as using Signals throughout our app has completely broken hot reload for all screens for us!
Try using signals_hooks!
SignalProvider doesnt actually work the way it looks like it should because it doesnt store the created signal in any kind of state.
Instead, i'd recommend having an InheritedSignal that accepts a pre-existing signal for access, and a SignalProvider which is a stateful widget that properly handles the lifecycle of the signal factory