Applying Dependency Injection in Flutter Using Injectable
Tags: flutter, dipendencyinjection, injectable, flutterdevelopment
Published: 2023-12-07 03:50:20

Dependency injection (DI) is a design pattern that promotes loose coupling and enhances the modularity and testability of your code. In the world of Flutter development, dependency injection becomes a crucial tool for managing the dependencies in a clean and efficient manner. One popular package for implementing dependency injection in Flutter is injectable. In this article, we will explore how to apply dependency injection in Flutter using the injectable package.

## What is Dependency Injection?
Dependency injection is a software design pattern where the components of a system are loosely coupled by injecting dependencies rather than hardcoding them within the components. This makes the system more modular, flexible, and easier to test.

In Flutter, dependencies might include services, repositories, or any other classes that a widget relies on to perform its tasks. Instead of creating instances of these dependencies directly within a widget, dependency injection allows us to provide these instances from the outside, making our code more maintainable and scalable.

## Using the injectable Package
The injectable package is a powerful and easy-to-use dependency injection package for Flutter. It provides a simple and concise syntax for defining and injecting dependencies. To get started, add the following dependencies to your pubspec.yaml file:

```yaml
dependencies:
  injectable:  
  get_it:
  
dev_dependencies:
  injectable_generator:
  build_runner:
```

Now, run `flutter pub get` to fetch the dependencies.

## Setting up injectable
Once the dependencies are added, you need to set up injectable in your project. Create a new file called injection.dart in your project's root directory. This file will contain the configuration for injectable.

```dart
// injection.dart

import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';

import 'injection.config.dart';

final GetIt getIt = GetIt.instance;

@injectableInit
Future<void> configureDependencies(String env) async {
  getIt.init(environment: env);
}
```

This file initializes the `GetIt` instance and sets up the necessary configuration for `injectable`.

## Defining Dependencies
Now, let’s define some dependencies. Create a new folder named `injections` and inside it, create a file named `injection_container.dart`. This file will contain the configuration for your dependencies.

```dart
// injections/injection_container.dart

import 'package:injectable/injectable.dart';

@module
abstract class InjectableModule {
  // Define your dependencies here
  // Example:
  // @lazySingleton
  // YourDependency get yourDependency => YourDependency();
}
```

In this file, you can define your dependencies using the `@lazySingleton`, `@singleton`, `@factoryMethod`, and other annotations provided by `injectable`. For example, a simple dependency might look like this:

```dart
@lazySingleton
YourDependency get yourDependency => YourDependency();
```

Generating Code
To generate the necessary code for `injectable`, run the following command in your terminal:

```bash
flutter packages pub run build_runner build --delete-conflicting-outputs
```

This command triggers the code generation process and generates the necessary files for dependency injection.

## Using Dependencies in Widgets
Now that your dependencies are set up, you can use them in your widgets. Import the `injection.dart` file and call the `configureDependencies` function in your `main.dart` file:

```dart
// main.dart

import 'package:flutter/material.dart';
import 'package:injectable/injectable.dart';
import 'injection.dart';

void main() {
  configureDependencies(Environment.prod);
  runApp(MyApp());
}
```

Now, you can use the `getIt` instance to access your dependencies in any widget:

```dart
// example_widget.dart

import 'package:flutter/material.dart';
import 'injection.dart';

class ExampleWidget extends StatelessWidget {
  final YourDependency yourDependency = getIt<YourDependency>();

  @override
  Widget build(BuildContext context) {
    // Use yourDependency here
    return Container();
  }
}
```

## Conclusion
Dependency injection is a powerful pattern that can greatly improve the structure and testability of your Flutter applications. The injectable package provides a convenient way to implement dependency injection in your projects. By separating concerns and promoting modular code, you can create more maintainable and scalable Flutter applications.