November 7, 2025
Flutter

What is dependency injection in flutter

Dependency Injection (DI) in Flutter (and more generally in software development) is a design pattern used to make your code more modular, testable, and maintainable by separating object creation from object usage.

Let’s break that down 👇


🧩 What It Means

Normally, when a class depends on another class, you might write something like:

class ApiService {
  void fetchData() => print('Fetching data...');
}

class UserRepository {
  final ApiService apiService = ApiService(); // 👈 creating dependency here

  void getUser() {
    apiService.fetchData();
  }
}

Here, UserRepository creates its own ApiService.
That makes it hard to test (you can’t easily mock ApiService) and hard to change (if ApiService needs parameters, every place that creates it must change).


💡 With Dependency Injection

Instead, you inject the dependency from outside:

class UserRepository {
  final ApiService apiService;

  UserRepository(this.apiService); // 👈 dependency is injected

  void getUser() {
    apiService.fetchData();
  }
}

Now you can easily provide any version of ApiService you like (real, mock, etc.) when creating UserRepository:

final userRepo = UserRepository(ApiService());

Or in tests:

final userRepo = UserRepository(MockApiService());

🧰 Common Ways to Do Dependency Injection in Flutter

Flutter doesn’t have built-in DI, but there are several popular packages that make it easy:

1. provider

Simplest way — you can provide dependencies using the widget tree.

void main() {
  runApp(
    Provider(
      create: (_) => ApiService(),
      child: MyApp(),
    ),
  );
}

Then retrieve it anywhere in the widget tree:

final api = Provider.of<ApiService>(context, listen: false);

2. get_it (Service Locator Pattern)

A lightweight and widely used DI library.

final getIt = GetIt.instance;

void setup() {
  getIt.registerLazySingleton<ApiService>(() => ApiService());
  getIt.registerFactory<UserRepository>(() => UserRepository(getIt<ApiService>()));
}

Then anywhere in your code:

final userRepo = getIt<UserRepository>();

This avoids passing dependencies down the widget tree.


3. riverpod

A more modern and powerful alternative to provider, also supports DI patterns:

final apiServiceProvider = Provider((ref) => ApiService());
final userRepoProvider = Provider((ref) => UserRepository(ref.read(apiServiceProvider)));

Then use it like this:

final userRepo = ref.read(userRepoProvider);

✅ Benefits of Dependency Injection

  • Easier testing: You can mock dependencies easily.
  • Better code reuse: Swap out implementations (e.g., fake API vs real API).
  • Decoupling: Classes don’t depend on specific implementations.
  • Cleaner architecture: Promotes SOLID principles.

⚠️ Common Pitfalls

  • Overusing DI can make small apps more complex than necessary.
  • Misusing Service Locators (get_it) can lead to hidden dependencies.
  • It’s best combined with architecture patterns like MVVM, Clean Architecture, or Bloc.

Related posts

How to start learning flutter from basic to advance

Dheeraj Pal

How to create a simple quiz app using flutter

Dheeraj Pal

How to setup Flutter with VSCode Step By Step Guide

Dheeraj Pal

2 comments

How to create a login page using flutter step by step guide - Dheeraj Hitech October 27, 2025 at 3:55 pm

[…] What is dependency injection in flutter […]

Reply
How to implement Login and Signup pages using Bloc in Flutter - Dheeraj Hitech October 28, 2025 at 4:59 pm

[…] What is dependency injection in flutter […]

Reply

Leave a Comment