Using a singleton for Bloc
Asked Answered
P

1

11

I know that some of my BLOCs will be instantiated only once throughout the app lifecycle. Is it bad practice or anti-pattern to create these BLOC classes as a singleton. Singleton can help in accessing the BLOC anywhere and also makes sure that the class is instantiated only once.

I can also ensure to be safe when using one BLOC inside another BLOC and passing around the singleton as if it were "just another" implementation.

What might be the effects of doing so?

Edit

I have two Blocs

  1. AuthenTicationBloc - this is a global bloc
  2. UserBloc - should exist only once (singleton)

The AuthenTicationBloc has to use the UserBloc inside it. If I made UserBloc a singleton , it would make it easy to just use it as UserBloc().

Othewise I had to create UserBloc as an instance variable in AuthenTicationBloc as follows:

class AuthenTicationBloc {
  UserBloc _userBloc;

  AuthenTicationBloc({@required UserBloc userBloc}) : _userBloc = userBloc;


  myMethod(){
    //use the userBloc
    _userBloc.setDetails();
  }
}


runApp(
  UserBloc userBloc = UserBloc();

  Provider(
    value: AuthenTicationBloc(userBloc: userBloc),
    child: MyApp(),
  ),
);

If I had to use the UserBloc down the widgetchain somewhere else I had to make the UserBloc also be provided globally as follows right?

UserBloc userBloc = UserBloc();

MultiProvider(
  providers: [
    Provider<AuthenTicationBloc>(
      value: AuthenTicationBloc(userBloc:userBloc),
    ),
    Provider<UserBloc>(
      value: userBloc,
    ),
  ],
  child: MyApp(),
);
Phraseologist answered 10/3, 2019 at 11:19 Comment(0)
V
6

The behavior stays the same. A singleton vs InheritedWidget doesn't change much

But it has a few architectural consequences, as you should use an InheritedWidget for BLoCs that aren't "instantiated only once throughout the app lifecycle."

Which means that:

  • you'll mix InheriedWidgets and Singletons in your app. Reducing consistency as you have two different way to create/use a BLoC
  • it becomes harder to adapt when the specs change. It is very possible that in the future, you may have to instantiate it more than once. That means you'd have to edit the whole application

On another note, singletons do not prevent some mistakes that InheritedWidgets do.

For example, it is impossible to have a circular dependency using InheritedWidgets, when it is definitely possible using singletons.


You're not winning much by using a Singleton vs InheritedWidget in term of code either.

There's a good chunk of libraries on Pub to make your job easier. Including provider:

runApp(
  Provider(
    value: MyBloc(),
    child: MyApp(),
  ),
);
Viddah answered 12/3, 2019 at 13:26 Comment(2)
Thanks for the explanation. Circular dependency might become a problem. My case of using a singleton is more of using it in another bloc rather than creating it as a property.. See my edit to the question.Phraseologist
The fact that InheritedWidgets requires to pass the BLoC as a parameter instead of directly using the variable is the reason why it prevents circular dependency.Lukewarm

© 2022 - 2024 — McMap. All rights reserved.