filiph / state_experiments

Companion repository to the "Build reactive mobile apps in Flutter" talk
https://www.youtube.com/watch?v=RS36gBEp8OI
910 stars 134 forks source link

Question regarding Singleton #3

Closed masseelch closed 6 years ago

masseelch commented 6 years ago

Hello,

i saw your video about state management and came here afterwards. (Great video, learned a lot and got a lot more questions)

Are there any drawbacks on using the inherited widgets as Providers for the BLoC's instead of a singleton? I just learned dart has any easy way to create singletons with factory constructors, so this seems like another (maybe good) way to go?

I have seen that you have one part of this repo which is called singleton, so i assume you did experiment with them. But why exactly do you seem to prefer the InheritedWidget way instead of the singleton?

I cannot find any questions anywhere concerning singletons vs InheritedWidget.

Thanks in advance for any answer :-)

JC

filiph commented 6 years ago

Thanks for the question!

The main difference between InheritedWidget and (the way we're using) a singleton is that the latter is used as a global variable. That means testing is really hard / impossible.

Take this fragment of a test:

final mockCart = MyMockCart();
return CartProvider(
  cart: mockCart,
  child: MyApp(),
);
expect(mockCart.triedContactingServer, isTrue);

In the example above, using something that's not a global variable allows us to mock it and then verify that MyApp uses the provided/inherited value correctly.

With a global variable, that's not possible. The app will always have access to that one Cart, which we won't be able to mock. That might mean that our tests are trying to actually contact the server, even in unit tests.

This is just one very concrete example why global singletons are not a good idea. There's a lot of discussion about other reasons to be found.

Singletons have their place (especially when they're not global, and when they stand for a resource that is always single — like the audio driver in games, for example). But for state management in a Flutter app, I'd recommend against them.

Still, we wanted to show it.

Let me know if that answers your question. I'm going to close this issue here. Feel free to re-open it. (But we might want to move this discussion elsewhere.)

masseelch commented 6 years ago

Thanks for the fast reply. I somehow did not see the Email, so please forgive my late reaction.

There is another question, which i have now.

Lets assume i have multiple BLoCs which i then need multiple ProviderWidgets for.

Is there a "cleaner" solution to

return CartProvider(
  child: BLoCProvider2(
    child: BLocProvider3(
      child [... several more Providers ...],
        child: MyApp()
    ),
  ),
);