What is Flutter Injectable?

In the world of software development, Dependency Injection (DI) is a powerful design pattern that promotes modular, scalable, and maintainable code. In Flutter, managing dependencies can sometimes become challenging, especially in large applications. This is where Injectable comes in a code generator for handling dependency injection in Flutter, built on top of the popular get_it package.

In this blog, we’ll dive deep into Flutter Injectable, exploring how it simplifies dependency injection, enhances your Flutter projects, and provides practical examples to get you started.

What is Dependency Injection?

Flutter Injectable

Before we jump into Injectable, let’s briefly recap what Dependency Injection is:

Dependency Injection is a technique where an object receives its dependencies from an external source rather than creating them itself. This promotes loose coupling between classes and makes the code easier to test and maintain.

In simpler terms, instead of a class creating its instances of dependencies, those dependencies are injected into the class from outside, usually by a DI container.

Why Use Injectable in Flutter?

While Flutter provides several ways to manage dependencies, manually injecting dependencies can lead to boilerplate code, especially as your application grows. Injectable, combined with get_it, streamlines this process by auto-generating the necessary code to manage your dependencies efficiently.

Key benefits of using Injectable:

  1. Auto-Generated Code: Injectable auto-generates code for DI, reducing boilerplate and potential errors.
  2. Scalability: Manages dependencies across large codebases seamlessly.
  3. Modularity: Promotes modular architecture, making it easier to test and maintain.
  4. Integration with GetIt: Seamless integration with get_it, a popular service locator in Flutter.

Setting Up Injectable in Flutter

Let’s walk through the steps to integrate Injectable into a Flutter project.

Step 1: Add Dependencies

First, add the necessary dependencies to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  get_it: ^7.2.0
  injectable: ^2.0.0

dev_dependencies:
  injectable_generator: ^2.0.0
  build_runner: ^2.1.11

After adding the dependencies, run flutter pub get to install them.

Step 2: Create the Injectable Configuration

Create a new Dart file named injection.dart in the lib folder. This file will configure Injectable and initialize get_it:

import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart'; // generated file

final getIt = GetIt.instance;

@InjectableInit(
  initializerName: r'$initGetIt', // default
  preferRelativeImports: true, // default
  asExtension: false, // default
)
void configureDependencies() => $initGetIt(getIt);
Step 3: Annotate Your Services

To inject dependencies, you need to annotate your classes. For example, let’s say you have a UserRepository and a UserService:

import 'package:injectable/injectable.dart';

@lazySingleton
class UserRepository {
  // Your implementation
}

@injectable
class UserService {
  final UserRepository userRepository;

  UserService(this.userRepository);
  
  // Your implementation
}

Here, @lazySingleton tells Injectable to create a single instance of UserRepository, which will be reused whenever it’s needed. The @injectable annotation on UserService ensures that it will be properly injected with its dependencies.

Step 4: Generate the DI Code

Now, let’s generate the code to wire everything together. Run the following command in your terminal:

flutter pub run build_runner build

This will generate the necessary code in the injection.config.dart file.

Step 5: Use the DI in Your Flutter App

With everything set up, you can now inject dependencies in your Flutter widgets or other classes:

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

void main() {
  configureDependencies();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final userService = getIt<UserService>();
    
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Injectable Example'),
        ),
        body: Center(
          child: Text('Welcome, ${userService.getUserName()}!'),
        ),
      ),
    );
  }
}

In this example, getIt<UserService>() retrieves the instance of UserService with all its dependencies automatically injected.

Advanced Usage of Injectable

Injectable is highly customizable and supports advanced features such as:

  1. Named Dependencies: You can have multiple implementations of the same interface by using named dependencies.
  2. Environment-Based Injection: Injectable allows you to define different sets of dependencies based on the environment (e.g., dev, prod).
  3. Modules: You can group dependencies into modules for better organization and reuse.

Conclusion

Injectable makes Dependency Injection in Flutter a breeze by automating the process of managing dependencies, reducing boilerplate code, and improving the scalability of your application. By following the steps outlined in this blog, you can integrate Injectable into your Flutter projects and take advantage of its powerful features.

Whether you’re building a small app or a large enterprise application, using Injectable ensures that your codebase remains clean, modular, and easy to maintain. Start using Injectable today and see the difference it makes in your Flutter development workflow!

Show Your Support

Explore Other Flutter Topics…

  1. What is Flutter
  2. Stateful VS Stateless Widget
  3. Page Transition in Flutter
  4. Web Animation in Flutter
  5. Async and Await in Flutter
  6. Dependency Injection in Flutter
  7. Flutter Reusable custom Widgets
  8. Flutter Custom Shapes
  9. Build Responsive UIs in Flutter using MediaQuery

6 Responses

Leave a Reply

Your email address will not be published. Required fields are marked *