What is Dependency Injection?
DI is a format sample in which a category requests dependencies from exterior sources as an alternative than growing them. It ability the established objects are injected or furnished to your class. The type doesn’t have to do any initialization by way of itself. It will get what it desires from the injector.
Loose coupling: When an object receives the object to be used from exterior sources, we name it unfastened coupling. In different words, the unfastened coupling capability that the objects are independent.
Tight coupling: When a crew of lessons is exceptionally structured on one another, it is referred to as tight coupling.
Dependency injection is one of the most realistic format patterns that enable builders to write loosely coupled code. It additionally helps to maintain our code greater testable.
Let us take an example,
When some category Jungle wishes type Animal to function its operation, category Jungle is known as Dependent, and category Animal is known as Dependency.
class Jungle {
Animal _animal = Animal();
void check() {
_animal.who();
}
}
class Animal {
void who() {
print("I am animal.");
}
}
void main(){
Jungle _jungle=Jungle();
_jungle.check(); //prints "I am animal".
}
In the above example, our class, Jungle, is tightly coupled. It ability the classification Jungle is particularly based on the dependency Animal.
If we desire to add a new animal Tiger, then there is no way to alternate the animal to Tiger as we have hardcoded Jungle and Animal classes.
Now the usage of dependency injection to clear up our problem.
void main(){
final Tiger _tiger=Tiger();
Jungle _jungle=Jungle(_tiger);
_jungle.check(); //prints "I am tiger".
}
class Jungle {
late Animal _animal;
Jungle(Animal animal) {
_animal = animal;
}
void check() {
_animal.who();
}
}
class Animal {
void who() {
print('I am animal.');
}
}
class Tiger implements Animal {
@override
void who() {
print('I am tiger.');
}
}
As we can see, we are injecting the dependency from the backyard into the implementation of the class.
Now we can create as many animals as feasible and inject them into the Jungle class.
In this way, our class, Jungle, is loosely coupled.
If we desire to recognize about Lion, create a lion object and inject it into the Jungle class.
Dependency injection is really helpful in Unit Testing due to the fact dependencies are injected outdoors in the class. That’s why our category is no longer any greater structured on different dependencies. And we can effortlessly check our category in isolation.
Constructor as Dependency Injection:
What is an Inherited Widget?
In flutter, the inherited widget is a base type that lets these lessons lengthen statistics below the tree from it. It works with the aid of informing registered construct references when an exchange occurs.
import 'package:flutter/material.dart';
class InheritedText extends InheritedWidget{
final String helloText='Hi from inherited widget';
final Widget child;
String get getHelloText=>helloText;
const InheritedText({required this.child}):super(child:child);
static InheritedText? of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<InheritedText>();
}
@override
bool updateShouldNotify(InheritedText old){
return true;
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InheritedText(
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Page1(),
),
),
)
);
}
}
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Page2();
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Page3();
}
}
class Page3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Page4();
}
}
class Page4 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final helloText= InheritedText.of(context)!.getHelloText;
return Text(
helloText,
style: Theme.of(context).textTheme.headline4,
);
}
}
Now, Inherited Widget helps us get admission to any objects, methods, variables, etc., described in the Inherited Widget in the widget tree.
But there nevertheless is a problem, Inherited Widget desires context to get entry to the object. We can’t inject this dependency interior the category which doesn’t have context.
So that’s a trouble now. What if we favor to get admission to dependencies interior the training like DB, Client, etc? There we may not have context, due to the fact they're simply easy everyday classes.
To overcome the hassle of the Inherited widget, there is get_it package.
https://pub.dev/packages/get_it