Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot reload with SignalProvider causes create to rerun again #365

Open
SPiercer opened this issue Jan 4, 2025 · 4 comments
Open

Hot reload with SignalProvider causes create to rerun again #365

SPiercer opened this issue Jan 4, 2025 · 4 comments

Comments

@SPiercer
Copy link

SPiercer commented Jan 4, 2025

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

@SPiercer
Copy link
Author

SPiercer commented Jan 4, 2025

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

@SPiercer
Copy link
Author

SPiercer commented Jan 5, 2025

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 registerLazySingleton or registerSingleton and 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 registerCachedFactoryParam instead of registerFactoryParam because 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(...)
);

@rodydavis
Copy link
Owner

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.

@SPiercer
Copy link
Author

SPiercer commented Jan 28, 2025

i used InhertedProvider from package:provider

check my fork : https://github.com/SPiercer/signals.dart/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants