Dependency injection is a technique in software development that promotes loose coupling and easy management of dependencies in an application. This concept can be implemented in Dart and Flutter projects using a package known as get_it. The get_it package acts as a service locator, providing a central registry for service objects that can be accessed across the Flutter application.
Get_it is a simple service locator for Dart and Flutter projects that can be used as an alternative to InheritedWidget or Provider to access objects from your UI code. Using get_it, you can access the same instance of a class across different parts of your Flutter app, reducing the need to create a new instance every time.
To use get_it, add it to your yaml file and set up a get_it instance. This can be done in the main function of your Dart file. The setup function for get_it is typically written in a Dart file separate from the main function.
1final getIt = GetIt.instance; 2 3void setup() { 4 getIt.registerSingleton<AppModel>(AppModel()); 5} 6
In the above example, we have created a new instance of the AppModel class and registered it with get_it. We can now access this instance from anywhere in our Flutter app.
Once you have registered a service with get_it, you can access it using the buildcontext context in your Flutter widgets. This allows your UI code to access the services it needs without directly depending on them.
1MaterialButton( 2 child: Text("Update"), 3 onPressed: getIt<AppModel>().update 4), 5
In the above example, we are accessing the update method of the AppModel class that we registered with get_it earlier.
To implement dependency injection with get_it, you can use it for both setter injection and constructor injection. This reduces the amount of boilerplate code you need to write in your Flutter app, making it easier to manage dependencies.
1class Example { 2 Service service; 3 4 Example() { 5 service = getIt<Service>(); 6 } 7} 8
In the above example, we are using constructor injection to inject an instance of the Service class into the Example class. This instance is retrieved from the get_it service locator.
Get_it also supports working with async functions. Register a service with an async function in get_it and then access it in your Flutter application.
1void setup() { 2 getIt.registerSingletonAsync<Service>(() async => await Service.create()); 3} 4
In the above example, we register a service with an async function that returns a Future of the Service class. This allows us to perform asynchronous operations when creating the service.
Setting up get_it in a Flutter project involves adding the get_it package to your project's yaml file and then initializing a get_it instance in your project's main function.
To start using get_it in your Flutter project, add it to your project's yaml file. This file is where you list all the dependencies for your project.
1dependencies: 2 flutter: 3 sdk: flutter 4 get_it: ^7.2.0 5
In the above example, we have added get_it as a dependency to our Flutter project. Before the version number, the caret (^) means that the project can use any version of get_it that is compatible with version 7.2.0.
After adding get_it to your yaml file, the next step is to set up a get_it instance. This is typically done in the main function of your Dart file. You can create a setup function for get_it and call this function in your main function.
1final getIt = GetIt.instance; 2 3void setup() { 4 getIt.registerSingleton<AppModel>(AppModel()); 5} 6 7void main() { 8 setup(); 9 runApp(MyApp()); 10} 11
In the above example, we have created a setup function that registers an instance of the AppModel class with get_it. We then call this setup function in our main function.
Once you have set up the get_it instance, you can access it anywhere in your Flutter app using the get_it global variable.
1class MyApp extends StatelessWidget { 2 3 Widget build(BuildContext context) { 4 final appModel = getIt<AppModel>(); 5 return MaterialApp( 6 home: Scaffold( 7 appBar: AppBar( 8 title: Text(appModel.title), 9 ), 10 ), 11 ); 12 } 13} 14
In the above example, we are accessing the get_it instance in a Flutter widget to get an instance of the AppModel class. We then use this instance to set the title of the app bar in our app.
The get_it package allows you to register services and access them anywhere in your Flutter app. This can be done using various methods, such as registering a simple service locator for an abstract class, registering a new instance or the same instance with get_it, and exploring different registration types.
To register a simple service locator for an abstract class, you can use the registerSingleton or registerLazySingleton methods provided by get_it.
1abstract class Service {} 2 3class ServiceImpl extends Service {} 4 5void setup() { 6 getIt.registerSingleton<Service>(ServiceImpl()); 7} 8
In the above example, we have defined an abstract Service class and a ServiceImpl class that extends Service. We then register ServiceImpl as a singleton instance of Service using the registerSingleton method.
With get_it, you can register a new or the same class instance. Registering a new instance means that every time you call get_it<Service>()
, you will get a new instance of Service. Registering the same instance means you will get the same service instance every time you call get_it<Service>()
.
1void setup() { 2 getIt.registerFactory<Service>(() => ServiceImpl()); // New instance 3 getIt.registerSingleton<Service>(ServiceImpl()); // Same instance 4} 5
In the above example, we register ServiceImpl as a factory, meaning a new instance will be created every time we call get_it<Service>()
. We also register ServiceImpl as a singleton, meaning the same instance will be returned whenever we call get_it<Service>()
.
Get_it offers different registration types such as lazy singletons, factory functions, and constructor injection. A lazy singleton is a singleton that is only created when it is first requested. A factory function is a function that returns a new instance of a class. Constructor injection is a form of dependency injection where dependencies are provided through a class constructor.
1void setup() { 2 getIt.registerLazySingleton<Service>(() => ServiceImpl()); // Lazy singleton 3 getIt.registerFactory<Service>(() => ServiceImpl()); // Factory function 4} 5
In the above example, we register ServiceImpl as a lazy singleton and a factory function.
Dependency injection is a software design pattern that allows us to develop loosely coupled code. It is a form of inversion of control; this means that the custom-written portions of a computer program receive the flow of control from a generic, reusable library. To implement dependency injection in Dart and Flutter, we can use the get_it package.
Get_it can be used for both setter injection and constructor injection. Setter injection is a type of dependency injection where the dependencies are provided through setter methods. In contrast, constructor injection is a type of dependency injection where the dependencies are provided through a class constructor.
1class Service {} 2 3class Example { 4 late Service _service; 5 6 // Setter injection 7 set service(Service service) { 8 _service = service; 9 } 10 11 // Constructor injection 12 Example(this._service); 13} 14 15void setup() { 16 getIt.registerSingleton<Service>(Service()); 17 getIt.registerSingleton<Example>(Example(getIt<Service>())); 18} 19
In the above example, we have an Example class that has a dependency on a Service class. We provide this dependency using both setter injection and constructor injection.
One of the advantages of using get_it is that it can reduce boilerplate code in your Flutter app. By registering your services with get_it, you can access them from anywhere in your app without having to instantiate them manually every time.
1void main() { 2 setup(); 3 runApp(MyApp()); 4} 5 6class MyApp extends StatelessWidget { 7 8 Widget build(BuildContext context) { 9 final example = getIt<Example>(); 10 return MaterialApp( 11 home: Scaffold( 12 appBar: AppBar( 13 title: Text('Example App'), 14 ), 15 body: Center( 16 child: Text('Service: ${example.service}'), 17 ), 18 ), 19 ); 20 } 21} 22
In the above example, we access the Example service from our app's UI code using get_it. This means we don't have to manually instantiate Example whenever we want to use it.
The get_it package supports working with async functions. This allows you to perform asynchronous operations when registering and accessing services in your Flutter app.
You can register a service with an async function in get_it. Creating the service allows you to perform asynchronous operations, such as fetching data from a database or a network request.
1Future<Service> createService() async { 2 // Perform async operations 3 return Service(); 4} 5 6void setup() { 7 getIt.registerSingletonAsync<Service>(createService); 8} 9
In the above example, we have an async function createService that returns a Future of Service. We then register this function with get_it using the registerSingletonAsync method.
Once you have registered a service with an async function, you can access it in your Flutter app using the getAsync method provided by get_it. This method returns a Future of the service, which you can await to get the actual service.
1class MyApp extends StatelessWidget { 2 3 Widget build(BuildContext context) { 4 return FutureBuilder<Service>( 5 future: getIt.getAsync<Service>(), 6 builder: (context, snapshot) { 7 if (snapshot.connectionState == ConnectionState.done) { 8 final service = snapshot.data; 9 // Use the service 10 return MaterialApp(/* ... */); 11 } else { 12 return CircularProgressIndicator(); 13 } 14 }, 15 ); 16 } 17} 18
In the above example, we use a FutureBuilder to await the Future returned by get_it.getAsync<Service>()
. Once the Future completes, we can use the service in our app.
The get_it package is a powerful tool for managing dependencies in Dart and Flutter applications. It provides a simple service locator that allows you to access the same instance of a class across your entire app. This reduces the need to create new instances and makes your code cleaner and easier to manage.
get_it can be used to implement dependency injection, a technique in software development that promotes loose coupling and easy management of dependencies in an application. This can be achieved using get_it for both setter and constructor injection, which reduces the boilerplate code you need to write in your Flutter app.
Furthermore, get_it supports working with async functions, meaning you can register a service with an async function in get_it and then access it in your Flutter application. This is especially useful for performing asynchronous operations when creating the service.
In conclusion, whether you are working with synchronous or asynchronous code, get_it has the tools to manage your services effectively and reduce boilerplate code. Its flexibility and ease of use make it an essential tool for any Dart and Flutter developer.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.