Flutter Dependency Inversion For Beginners | Complete Guide

Поділитися
Вставка
  • Опубліковано 3 січ 2025

КОМЕНТАРІ • 125

  • @nosmirck
    @nosmirck 5 років тому +93

    Great video, however, I believe you need to read a bit more about the concepts, I known they can be confusing, but you got quite a few things wrong.
    First of all, the design principle (from the SOLID principles) we want to satisfy is Dependency Inversion, which basically states two things: 1) high level modules should not depend on low level modules, both should depend on abstractions (or interfaces)
    2) abstractions should not depend on details or concrete implementations, they should depend upon abstractions.
    Now, this means we should provide our dependencies as abstract classes or interfaces that contain nothing more than what defines the class (no details on the implementation).
    So, to solve this problem, we rely on one Inversion of Control (IoC) technique.
    IoC basically means that, dependant classes should not have the responsibility of creating concrete instances for their dependencies, instead, the flow of control is inverted and delegates the responsibility to something else to provide the class with the concrete implementations of their dependencies, of course, only knowing about the abstractions, not the actual concrete implementation.
    Now, Dependency Injection Is an IoC technique, and strictly means injecting the dependencies through constructor (also accepted using with setters, but it's more common with the constructor because is verbose and explicit). This can be implemented manually (like you showed) or through a framework (like Autofac, Ninject, Unity for C#) that will resolve de dependencies in runtime, they depend heavily on reflection in order to instantiate dependant classes without you explicitly passing the dependencies through the constructor, a thing that is not possible with flutter since Dart's mirrors are disabled, however, there are other solutions, using code generation. DI packages for flutter like inject and kiwi rely on this. I personally don't like code generation since I like to have full control on every line of my code, but it's ok to use on some cases, which leads me to what I actually use: Service Locator.
    A Service Locator (like get_it) is another technique that helps inverting the control, the dependant classes still have the responsibility of asking for the dependencies, but no need to actually instantiate anything, the locator will take care of that (it has the control, hence, inversion achieved), one disadvantage is that the dependencies are less verbose and strict (you can't know what a certain class needs unless you look at the code, while with DI, just by looking at the constructor, you know exactly what it depends on).
    Now, using an InheritedWidget is not a way of achieving Dependency Inversion much less a way to Inject Dependencies.
    An Inherited Widget is nothing more than a node in the tree that usually sits on top of all other nodes that might depend on something and it provides the first appearance of said dependency (kind of like a locator, but not really) through a static method, which means this call is cheap, no need to traverse the tree up to look for something, let alone traverse back down to notify dependants, so, the static "of" method (that actually you can call whatever you want, nothing explicitly says it needs to be called "of", it's just a formality, you only need to implement is updateShouldNotify, I could explain deeper, but I'm lazy and this comment is getting too long) will simply call inheritFromWidgetOfExactType that, if you see the implementation, basically returns the first InheritedWidget instance from the bottom up where it was called of the type requested from the BuildContext (current state of the widget tree).
    In conclusion, what you try to explain is good, having a good architecture is key, but you messed and mixed concepts, probably because you never had to implement a DI framework or a Service Locator from scratch, which gives a lot of knowledge on how the Inversion of Control works for Dependency Inversion Principle to be achieved.
    Hope that helps! And please don't take my comment personally, I just want to make things clear for you and everyone else.
    Have a great day and keep making awesome videos!

    • @PhenomenonVFX
      @PhenomenonVFX 5 років тому +15

      I feel like this should be an article on its own and will make for a very interesting read. If you ever write an article on this topic with Flutter or Dart in focus, I will love to read it.

    • @FilledStacks
      @FilledStacks  5 років тому +34

      Thank you for the amazing feedback. I appreciate the time taken to write the comment. And you don't have to mention taking it personally I'm here to learn and so is everyone else. I give and have been in many code reviews. Taking it personal would surely lead to death in this industry 😅 . I think however you should probably read up a bit more, or at least think of the concepts logically and you'll see you're bringing additional baggage into a different conversation. I see it happening a lot.
      There's a few things I'd object to. As any engineer would. The first thing is the reason I made this video. That reason is that senior engineers tend to make things more complicated than it is, and this usually happens by attaching additional things to their explanations making problems appear more difficult than they are. So to the beginners reading the above comment, it's not that complex. The concepts spoken about here you learn over time by learning techniques such as the one in this video as you require them. It really is that simple. This is one technique in the IoC group.
      Here's some things the video is not about:
      - Solid principles: Which I've been implementing in practice (being of C# decent) very frequently.
      - The entire concept of Inversion of Control.
      - Teaching beginners that all these things are tightly connected (talking about the ideas and concepts). The architecture community tend to favour building smaller pieces of specific components in their code but the ideas still seem to be stuck to one another. For instance in this example. I only want to teach dependency injection. Wiki definition "In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object". I don't want to teach more than that. That's how I framed it and that's what I taught. This video is to teach "How to write code to supply your other objects with classes THEY DEPEND ON". Attaching additional ideas to that simple concept IS why I'm making this video. To show that it's not a daunting task, and it's pretty simple to do in Flutter and anywhere else.
      My channel and my videos will always be dedicated to showing that "It actually is that simple". It's the main reason I WANT to do it. The software engineering community has this "Keep it simple" mindset but don't apply it when they're teaching. Although I can't blame them most of the engineers are not that great when it comes to relaying information that's happening in their head. Okay on to address some of what you said, which in my opinion is wrong there's quite a lot in here. And I wouldn't want beginners to be confused.
      "Dependency Injection ... strictly means injecting the dependencies through constructor" - This is just wrong. Dependency injection is writing code to supply one object with another. That's all it is. I'm NOT talking about IoC. It's one of those techniques, but Dependency injection can stand on it's own without that.
      "InheritedWidget is not a way of achieving Dependency Inversion" - You're kind of right but this videos is about Dependency injection not Dependency Inversion. Even though they are related they are not the same thing. One is the act of making your code less dependent on other concrete implementations and the other is supplying your code with concrete implementations. We should be able to agree that those are different. The latter, Dependency injection does not depend on the implementation so whether "An Inherited Widget is nothing more than a node in the tree that usually sits on top of all other nodes" it still gets the work done. Which is to Inject the dependency into the Class that requires it.
      "what you try to explain is good, but you messed and mixed concepts" - haha, I like this one but it's exactly what you're doing. Mixing Dependency Injection with Dependency Inversion with the entire IoC class of techniques with a bonus of strict personal implementation guides.
      " probably because you never had to implement a DI framework" - I have made a tiny one, and I do have a solid understanding of Inversion of Control works for Dependency Inversion Principle although. Once again, to teach things separately, this video is not about that, or trying to teach that. It's only about Dependency Injection which to end of again. "dependency injection is a technique whereby one object supplies the dependencies of another object"
      Thank you for the explanation of IoC and Dependency Inversion. I'm sure I'll cover a video on that in the Future and I'll point to this comment.

    • @FilledStacks
      @FilledStacks  5 років тому +3

      @@PhenomenonVFX You hit the nail on the head! What Luis is talking about is a much much much broader concept. A video and article on that would be a completely different video and probably be a series if you expect to cover everything.

    • @narcodico
      @narcodico 5 років тому +6

      Dart is not C#, Flutter is not Xamarin(thank god!).

    • @FilledStacks
      @FilledStacks  5 років тому +3

      Haha hey man I'm a Xamarin veteran 😅 I still carry the scars it left me. I jumped ship in 3 seconds after reading about and using Flutter 🤣

  • @officialismailshah
    @officialismailshah 3 роки тому

    BEST GUIDE TO DEPENCY INJECTION FOR BEGINNER REALLY HELPED ME A LOT , I AM NEW TO DEPENDENCY INJECTION KIND STUFF.....

    • @FilledStacks
      @FilledStacks  3 роки тому +1

      I'm very happy to hear that. It's quite old, but it still holds up I see!

  • @arnaudduquenoy2061
    @arnaudduquenoy2061 3 роки тому +1

    Thank you very much ! your tuto is golden :) It missed by exemple in Resocoder tutos WHY using INJECTABLE and you fully explained it!

    • @FilledStacks
      @FilledStacks  3 роки тому

      thank you for the nice feedback. I'm happy it was valuable to you

  • @SilasSWF
    @SilasSWF 5 років тому +1

    Very good explanation. Thank you!

  • @pranthonyaquino
    @pranthonyaquino 3 роки тому

    Excellent video, great explanation.

    • @FilledStacks
      @FilledStacks  3 роки тому +1

      Great!! I'm happy it's still relevant. Thanks for watching and leaving a comment.

  • @elsaiedsamaka7373
    @elsaiedsamaka7373 4 роки тому +1

    that was a great explanation

  • @iamyogik
    @iamyogik 5 років тому +2

    U r the best😄

    • @FilledStacks
      @FilledStacks  5 років тому +1

      Yeeaaah. I'll take that as a fact 😁

  • @alliu6757
    @alliu6757 5 років тому +1

    Thank you for your video, could you publish a video about how to do the test with Provider?

    • @FilledStacks
      @FilledStacks  5 років тому

      Thanks. I did here I go over how to abstract for unit testing using either get_it or provider (ua-cam.com/video/oZW3Eb3J9s0/v-deo.html)

  • @japiebosch6281
    @japiebosch6281 Рік тому

    Great video!

    • @FilledStacks
      @FilledStacks  Рік тому

      I appreciate that! Thanks for watching

  • @ahmadkhan271
    @ahmadkhan271 3 роки тому

    it was really helpful. simple and clear

    • @FilledStacks
      @FilledStacks  3 роки тому

      I'm very happy to hear that and thank you for leaving a comment about it.

  • @jhvkgvb
    @jhvkgvb 5 років тому

    Great video mate! Keep it up! 🌟

  • @gmc254quads6
    @gmc254quads6 5 років тому +1

    Get It! My favorite!

    • @FilledStacks
      @FilledStacks  5 років тому

      Get it is pretty sick when you're not a big fan of the verbose inherited widget style coding. Easy to use, easy to write bad code with as well 😄

  • @rikyriky966
    @rikyriky966 4 роки тому

    I also use Provider. It is rock solid. No problems at all.
    One question: I often need method functions inside of stateful or stateless widgets.
    For example:
    buildProfileInfoSection()
    However, since we cannot use Provider without “context”, it is a pain. So for every method, I have to provide the related provider variable as an argument.
    For example:
    buildProfileInfoSection({@required StyleProvider styleProvider}) {........}
    Or provide the context of the widget as an argument.
    buildProfileInfoSection({@required BuildContext context}) {
    StyleProvider styleProvider = Provider.of(context);
    .
    .
    .
    }
    Do you know a better approach? Thanks.

    • @FilledStacks
      @FilledStacks  4 роки тому

      Yes, I use provider through stacked, so I would simply use a ViewModelWidget for something like that which will help me get the model in that widgets build method.

  • @ketanchoyal7024
    @ketanchoyal7024 5 років тому +1

    What if we use get_it and provider library at the same time? then can we inject into object without context?

    • @FilledStacks
      @FilledStacks  5 років тому +1

      Yes. If you watch my architecture video on provider then you'll see that's exactly what I do.

  • @oliverbytes
    @oliverbytes 5 років тому

    What's the difference by using a Static Class for Services? Or Pros and Cons? Opinions, please. thanks a lot

    • @FilledStacks
      @FilledStacks  5 років тому

      Static classes are harder to test, abstraction is difficult so all your code becomes dependent on that class. The loss of abstraction is the biggest one since you lose a lot of benefits from abstraction. Which you can see in my other videos. I use static classes if I won't be testing something or it's code i just want to collect under a single class.

    • @oliverbytes
      @oliverbytes 5 років тому

      @@FilledStacks Thanks a lot. currently I don't do Unit Testing so I guess it's still okay to use Static Classes right? Also, I'm new to flutter and dart so hopefully I understand all you're saying. Do you have a resource why abstraction is important?

  • @rubinbajracharya9319
    @rubinbajracharya9319 5 років тому +1

    Hi there, Can you tell me how we can inject SharedPreferences Instance using get_it and use it as well.

    • @FilledStacks
      @FilledStacks  5 років тому +1

      Register it with the service locator and request it where you require it. I show it in this post www.filledstacks.com/snippet/shared-preferences-service-in-flutter-for-code-maintainability

  • @PaWLO1501
    @PaWLO1501 5 років тому

    Hey a have a problem with get_it. How to register a class which has constructor with parameter? For example I need to create instance of class Foo which has constructor Foo(SomeDependency object). I've tried something like this but won't work: getIt.registerSingleton((SomeDependency object) => Foo(object));

    • @FilledStacks
      @FilledStacks  5 років тому

      Hi. i haven't looked at that. I've never had to do that.

  • @ChirantarGupta
    @ChirantarGupta 4 роки тому

    Hi, it was a great video. Can you make a video series where we can create some simple app where we are using dependency injection and other standard practices? Not that much long series but where we can use get an idea.

    • @FilledStacks
      @FilledStacks  4 роки тому +2

      Yes, I've made 2 of those already. The firebase series which has 10 videos and the Flutter architecture series which has 8 videos. It's all in my playlists.

    • @ChirantarGupta
      @ChirantarGupta 4 роки тому

      @@FilledStacks great I will check them out.

    • @FilledStacks
      @FilledStacks  4 роки тому

      @@ChirantarGupta Awesome

  • @nishantdesai3705
    @nishantdesai3705 5 років тому

    how to use routing when following provider pattern ?
    is there anything we can do about it ? I have a basic todo app with authentication, it has 2 screens
    1. screen which lists todos
    2. settings screen from where you can logout
    now both of these screens will require User instance provider but If I use routing then I cannot share same instance of User provider on both screens right ?
    or is there a way to do that other than wrapping your app in provider ? because I might have other 2 providers that I need on both screen and wrapping my app inside all those 3 nested providers does not makes sense because it's just a hack not a solution

    • @FilledStacks
      @FilledStacks  5 років тому

      My tutorial sets up routing for provider as well. But state management doesn't interfere with navigation so you can just use it as you normally would. Just look at my architecture tutorial and you'll see how to make an authentication service. Then use that in both of your models to perform the actions you want to.

  • @nazxuul
    @nazxuul 5 років тому

    Hi, I am very much a neophyte here and I don't understand the point of get_it. I can easily create a singleton in Dart and import it wherever I need - so why do I need get_it at all? Of course, I have the disposal problem but it seems get_it doesn't solve this.

    • @FilledStacks
      @FilledStacks  5 років тому

      Get_it is just a simple service_locator. It's a good idea not to have global objects floating around in your code. I point that out during the cons. It helps keep the architecture easy to read and understand by requesting your types from it so it has a single place where all of that lives. If you don't see the point of or haven't used service locators then read up on the SOLID principles you might be writing code that won't be easy to maintain down the line.

  • @WorstDeveloper
    @WorstDeveloper 5 років тому

    I'm a beginner and have some questions.
    1. How do you update values and listen to values in order to rerender widgets with get_it?
    2. Can you explain more about disposal? What is it and how do you do it?

    • @FilledStacks
      @FilledStacks  5 років тому +1

      1. You don't update and render from get it. that's a service locator to help with Dependency Injection.
      2. Disposing is to help release memory after you've used it to avoid leaks and crashes. it's also for cleanup to avoid old objects responding or floating around.

  • @pradeep422
    @pradeep422 5 років тому

    dont u think testing suks when we use singletons, may be im wrong can u provide a widget testing example includes provider with singletons....

    • @FilledStacks
      @FilledStacks  5 років тому +1

      I don't think so. Unit testing is pretty easy with provider since you can register any implementation you want and also swap out implementations on the fly. I test my services on their own. Integration testing through the widgets will use fake implementations because the bulk of the unit tests are done directly on the service.

  • @narcodico
    @narcodico 5 років тому

    I personally prefer to use get_it to instantiate stuff like services and provider to give access to stuff like Streams from services. I'm curious about your approach to disposing get_it instances/singletons resources(stream for example, when you only use get_it).

    • @FilledStacks
      @FilledStacks  5 років тому +1

      I do the same thing, In the architecture that I explained in my Provider architecture video the models for the views are all ChangeNotifiers. Dispose is called on the models already so all you have to do it override the dispose method in the model and remove your subscriptions to streams or do whatever clean up you want to. Additionally in the BaseView you can override your dispose call and then call a custom cleanup function on all the models that's inherited from the BaseModel. This will be done explicitly before the super.dispose call in the base view.
      As for singletons I don't clean them up. I'll look into calling unregister on the service locator after the runApp completes. That might work, or just clear all registrations from the GetIt instance.

    • @narcodico
      @narcodico 5 років тому +1

      I would much rather use StreamProvider than ChangeNotifierProvider when it comes to streams, especially if they are from firebase. I find pairing up ChangeNotifierProvider with a ChangeNotifier viewmodel works great when working with futures.

    • @FilledStacks
      @FilledStacks  5 років тому

      @@narcodico True, that is best if you're supplying your stream directly to the UI. I get all my data from my logic so the model subscribes to the stream and then updates my view for me. Either way is great it's just personal preference at the end of it. As long as you know how to get that data to your UI in a nice way everything should be good.

    • @tylerthornton9611
      @tylerthornton9611 5 років тому +1

      @@FilledStacks I really appreciate when you make videos like this, where you explain your reasoning in depth, and what the tradeoffs are for different ways of doing things.
      I'm using flutter to learn OOP and app development. I've been studying your two architecture guides and Jeff Delaney's Flutter/Firebase with Provider article, and I'd be interested in a video like this one that explains using streams in your architecture, rather than maps from JSON (especially since so many people new to Flutter are encouraged toward Firebase/Firestore for database services in the developer's material). It seems to me that there's a lot of room for newer programmers to get lost within "as long as you know how to get that data to your UI in a NICE way...." 🙂 Thanks again for all you do for the Flutter community.

    • @FilledStacks
      @FilledStacks  5 років тому

      @@tylerthornton9611 I appreciate the feedback man. I really do. Thanks.
      In the "Building a Feedback app" video I use the firestore streams to automatically update my UI. Is it something like that? In there I use streams through services in the models. That seems to be what you're referring to. If not please correct me.
      I do agree there's quite a lot of room to get lost. I'll try my best to shed some more light around that topic and the many others that I still have to cover. Thanks for watching the video and taking the time to reply.

  • @lucasvazquez4961
    @lucasvazquez4961 5 років тому

    If you have a provider that depends on another provider, what would you use to make this injection? Get_it?

    • @FilledStacks
      @FilledStacks  5 років тому +2

      For now yes. V3 of Provider introduces something called ProxyProvider where you can provide providers with values that's already registered in Provider. It's a bit messy in my opinion so I still keep get_it around. This way I can easily inject into objects that don't have the BuildContext.

  • @ben6
    @ben6 3 роки тому

    Oh so its the less boiler plate and less complicated version of Dagger (And Hilt).

    • @FilledStacks
      @FilledStacks  3 роки тому

      Dagger is super light on the boilerplate so I don't think it's less. but with the new Stacked app setup we have it's definitely less.

  • @bert.m
    @bert.m 4 роки тому

    Can you please make a course for flutter, dart, firebase and more ❤️

    • @FilledStacks
      @FilledStacks  4 роки тому +1

      I have a free course/sereies for firebase on my channel. I don't know enough about dart to make a course for it.

  • @SEOTADEO
    @SEOTADEO 3 роки тому

    good video, I found myself in a place where every service had it's own singleton which produced a lot of boilerplate and made it hard to reset the services at runtime. I'll ise get_it from now on.

    • @FilledStacks
      @FilledStacks  3 роки тому

      Yeah, it's a nice step up. It's very easy to use and has a lot of power.

  • @cloud15487
    @cloud15487 5 років тому

    thanks for the video :-)

  • @peekpt
    @peekpt 5 років тому

    Very nice, I use get _it, but now I will start using provider. BTW the dev is already experimenting lazy loaded providers.

    • @FilledStacks
      @FilledStacks  5 років тому

      I use provider and get_it in my architecture. I'm busy with a new video to show how we can use Provider for all dependency injection. Even into classes that doesn't have the BuildContext.

    • @peekpt
      @peekpt 5 років тому

      @@FilledStacks IDK if mixing both is good, flutter is all meant to be mixing logic and UI. provider will take care of disposing values and if you are layering services is one more job for you to take care of. Disposing a service that might be in use could cause a lot of trouble. I have production app with RxCommand and get_it but there's Pros and Cons. From my experience I prefer more having mixed things but less code to worry about. Singleton in flutter is still a static value anyway.

    • @FilledStacks
      @FilledStacks  5 років тому

      Could be your experience. Provider I use for the state management capabilities only, updating my UI when things have changed. GetIt I use for injecting in to services, as far as I know based on my architecture (ua-cam.com/video/kDEflMYTFlk/v-deo.html) it's much better when mixing both. Disposing is taken care of provider for the models, you can just override the dispose in each model that uses a service and it'll get called so you can clean up your code. If you want more mixed things with less code to worry about then get_it + provider would be perfect, watch my architecture vid and see how small each of my models are:) I'm busy with a provider only architecture. It's a lot more code and currently I don't see any added benefits besides the fact that there's no global service locator.

  • @sanal.abraham
    @sanal.abraham Рік тому

    consider ddd pls

    • @FilledStacks
      @FilledStacks  Рік тому +1

      I haven't found that large amounts of boilerplate works well in relation to speed of development, effectiveness during code hours and speed of onboarding. I use MVVM through stacked.
      If you're only talking about creating a domain language then I do that already. But not the series resocoder did, I'm not interested in the architecture at this point.

    • @sanal.abraham
      @sanal.abraham Рік тому

      @@FilledStacks Thank you for the argument FS. I find it valid.
      Ubiquitous language is certainly one of the skill I am looking to develop by practicing DDD but I am struggling to get the essence of DDD.

    • @FilledStacks
      @FilledStacks  Рік тому +1

      @@sanal.abraham there must be many tutorials about it and talks by now. Resocoder did a whole series about it and I've seen many on stage talks about it.

    • @FilledStacks
      @FilledStacks  Рік тому +1

      @@sanal.abraham good luck with learning it. And thanks for watching 😊

    • @sanal.abraham
      @sanal.abraham Рік тому

      @@FilledStacks Thank you for this channel :)

  • @cagrakgul6157
    @cagrakgul6157 5 років тому

    Awesome :)

  • @rehan-6377
    @rehan-6377 Рік тому

    Thanks

    • @FilledStacks
      @FilledStacks  Рік тому

      It's my pleasure. I'm happy it's still helpful

  • @sayedragab162
    @sayedragab162 2 роки тому

    This is a service locator and not dependency injection

  • @vipulbansal361
    @vipulbansal361 Рік тому

    Great

  • @Nobody-ky7sl
    @Nobody-ky7sl 5 років тому +1

    Nicee

  • @faizulla5838
    @faizulla5838 Рік тому

    Dependency Inversion and Dependency Invgection is ather way .... wron topic

    • @FilledStacks
      @FilledStacks  Рік тому

      I think think the topic is correct. But at the time I did not make it clear that service location is also a form of Dependency Inversion, and that's what I'm showing with get_it.

  • @subramaniams5589
    @subramaniams5589 4 роки тому

    great video. kindly remove the background music pls. thanks

    • @FilledStacks
      @FilledStacks  4 роки тому +3

      Thank you . I won't do that. Music is only there when I'm not coding. I like the way it sounds so it'll stay there. Thanks for watching :)

  • @Ibrah_id
    @Ibrah_id 4 роки тому

    nicce !

  • @HousseinDroubi-o9i
    @HousseinDroubi-o9i 6 місяців тому

    Hello man.

  • @faheemahmad5853
    @faheemahmad5853 Рік тому

    did not understand at all! need a simple app

    • @FilledStacks
      @FilledStacks  11 місяців тому

      This is a software engineering concept, it doesn't have much to do with apps. This is just a general engineering principle. If you don't understand it you likely don't grasp the fundamentals of object oriented programming yet. So I'd suggest learning programming without a framework like Flutter.