DEV Community

vmodal_ai
vmodal_ai

Posted on

Flutter Dependency Injection Made Simple: Build Scalable Apps with get_it (Beginner to Production Guide)

As your Flutter application grows, creating services like AuthService or ApiService in multiple places can make your code difficult to maintain and test.

That's why professional Flutter developers use Dependency Injection (DI).

In this tutorial, you'll learn how to implement Dependency Injection in Flutter using the get_it package.


What Is Dependency Injection?

Dependency Injection is a design pattern where a class receives its dependencies instead of creating them.

Without Dependency Injection

class LoginController {
  final AuthService authService = AuthService();
}
Enter fullscreen mode Exit fullscreen mode

With Dependency Injection

class LoginController {
  final AuthService authService;

  LoginController(this.authService);
}
Enter fullscreen mode Exit fullscreen mode

This approach keeps your code loosely coupled, reusable, and easier to test.


Why Use Dependency Injection in Flutter?

Dependency Injection helps you build production-ready Flutter apps by providing:

  • Better code organization
  • Easier testing
  • Reusable services
  • Loose coupling
  • Improved scalability

Install get_it

Add the package to your project:

dependencies:
  get_it: ^8.0.0
Enter fullscreen mode Exit fullscreen mode

Then run:

flutter pub get
Enter fullscreen mode Exit fullscreen mode

Create a Service

class AuthService {
  bool login(String email, String password) {
    return email.isNotEmpty && password.isNotEmpty;
  }
}
Enter fullscreen mode Exit fullscreen mode

Register Dependencies

Create a service_locator.dart file.

import 'package:get_it/get_it.dart';

final getIt = GetIt.instance;

void setupDependencies() {
  getIt.registerLazySingleton<AuthService>(
    () => AuthService(),
  );
}
Enter fullscreen mode Exit fullscreen mode

Initialize it before your app starts:

void main() {
  setupDependencies();
  runApp(const MyApp());
}
Enter fullscreen mode Exit fullscreen mode

Access the Service

Retrieve the registered service anywhere in your app.

final authService = getIt<AuthService>();

authService.login(
  "john@example.com",
  "password123",
);
Enter fullscreen mode Exit fullscreen mode

Constructor Injection

Instead of creating services inside a class, inject them through the constructor.

class LoginController {

  final AuthService authService;

  LoginController(this.authService);

}
Enter fullscreen mode Exit fullscreen mode

Create the controller like this:

final controller = LoginController(
  getIt<AuthService>(),
);
Enter fullscreen mode Exit fullscreen mode

Constructor injection improves maintainability and makes unit testing much easier.


Singleton vs Factory

Singleton

One shared instance for the entire application.

getIt.registerSingleton(
  AuthService(),
);
Enter fullscreen mode Exit fullscreen mode

Lazy Singleton

Creates the object only when it's first requested.

getIt.registerLazySingleton(
  () => AuthService(),
);
Enter fullscreen mode Exit fullscreen mode

Factory

Creates a new object every time.

getIt.registerFactory(
  () => LoginController(
    getIt<AuthService>(),
  ),
);
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Register dependencies in one place.
  • Prefer constructor injection.
  • Use Lazy Singleton for shared services.
  • Use Factory for controllers or view models.
  • Avoid creating services directly inside widgets.

Conclusion

Dependency Injection is one of the most important architectural patterns in Flutter. Combined with get_it, it helps you write cleaner, testable, and scalable code.

Whether you're building a small project or a production application, learning Flutter Dependency Injection will improve your app architecture and make future development much easier.


Tags

#flutter
#dart
#getit
#dependencyinjection
#architecture
Enter fullscreen mode Exit fullscreen mode

Top comments (0)