Injectable Package in Dart for Dependency Injection | Dependency Injection in flutter

The injectable package in Dart is used for Dependency Injection (DI). It helps automatically generate and manage dependencies, making code cleaner, modular, and testable.

What is Dependency Injection (DI)?

Dependency Injection is a design pattern where a class gets its dependencies from an external source instead of creating them itself.

For example, instead of doing this:

class UserService {
  final ApiService apiService = ApiService(); // Directly creating instance ❌
}

With DI, you inject the dependency from outside:

class UserService {
  final ApiService apiService;  // Injected from outside ✅
  UserService(this.apiService);
}

This makes the code loosely coupled, more maintainable, and testable.

Complete Example of Dependency Injection in Dart using injectable and get_it

Example will show you step by step how dependency injection works in Dart/Flutter using the injectable package.

Step 1: Add Dependencies

Add these in pubspec.yaml:

dependencies:
  get_it: ^7.2.0
  injectable: ^2.3.0

dev_dependencies:
  build_runner: ^2.4.0
  injectable_generator: ^2.4.0

then run in terminal:

flutter pub get

Step 2: Create Dependency Injection Setup

Create a new file: di_setup.dart

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

final getIt = GetIt.instance; // Service locator instance

@InjectableInit()
void configureDependencies() => getIt.init(); // Initializes dependencies

Step 3: Create a Service Class

Create api_service.dart

import 'package:injectable/injectable.dart';

@LazySingleton()  // Ensures only one instance is created when first needed
class ApiService {
  ApiService() {
    print("ApiService Created");
  }

  void fetchData() {
    print("Fetching data from API...");
  }
}

Step 4: Create a Repository That Uses This Service

Create user_repository.dart

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

@LazySingleton()
class UserRepository {
  final ApiService _apiService;

  UserRepository(this._apiService); // Dependency Injection in Constructor

  void getUserData() {
    _apiService.fetchData();
  }
}

UserRepositorydepends onApiService, but it does not create it manually.Instead, injectableinjects an instance automatically.

Step 5: Generate Code for Dependencies

Run this command to auto-generate dependency registration:

flutter pub run build_runner build

This will create a file di_setup.config.dart, which handles all dependency registration automatically.

Step 6: Use Dependencies in main.dart

Modify main.dart to initialize and use dependencies:

import 'package:flutter/material.dart';
import 'di_setup.dart';
import 'user_repository.dart';
import 'package:get_it/get_it.dart';

void main() {
  configureDependencies(); // Initialize dependencies
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Retrieving instance of UserRepository
    final userRepository = GetIt.instance<UserRepository>();

    return Scaffold(
      appBar: AppBar(title: Text("Dependency Injection Example")),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            userRepository.getUserData(); // Calls fetchData() from ApiService
          },
          child: Text("Fetch Data"),
        ),
      ),
    );
  }
}

How the Flow Works

1️⃣ main.dart calls configureDependencies(), which initializes all dependencies.
2️⃣ @LazySingleton() ensures only one instance of ApiService and UserRepository is created.
3️⃣ In HomeScreen, we retrieve UserRepository from getIt instead of creating it manually.
4️⃣ Clicking the button calls userRepository.getUserData(), which internally calls fetchData() from ApiService.
5️⃣ The ApiService prints “Fetching data from API…” to the console.

So, @LazySingleton() in Dart (injectable) – When, Why & Benefits

🔹 What is @LazySingleton()?

@LazySingleton() is an annotation in the injectable package that registers a class as a singleton, but it will only be created when first needed (lazily).


🔍 Why Use @LazySingleton()?

1️⃣ Saves Memory: Creates the object only when it’s first required, unlike @Singleton() which initializes at app startup.
2️⃣ Improves Performance: Avoids unnecessary object creation at the beginning, reducing startup time.
3️⃣ Manages Global Services Efficiently: Ensures a single instance is used across the app, preventing redundant instances.
4️⃣ Better Dependency Management: Makes dependency injection smoother, reducing tight coupling.
5️⃣ Easier Testing: Enables injecting mock services during testing.

📅 When to Use @LazySingleton()?

✅ When you need a single instance of a class but don’t want to create it until it’s first used.
✅ When using services, repositories, or APIs that are shared across multiple parts of the app.
✅ When an object’s creation is expensive, so delaying it saves resources.

🛑 When NOT to Use It?

❌ If the class should always be available at app start, use @Singleton().
❌ If the class needs to have multiple instances, use @Factory().

Leave a Reply

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

web_horizontal
About Us Disclaimer Privacy Policy Terms & Conditions Contact Us

Copyright © 2023 ResearchThinker.com. All rights reserved.