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();
}
With Dependency Injection
class LoginController {
final AuthService authService;
LoginController(this.authService);
}
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
Then run:
flutter pub get
Create a Service
class AuthService {
bool login(String email, String password) {
return email.isNotEmpty && password.isNotEmpty;
}
}
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(),
);
}
Initialize it before your app starts:
void main() {
setupDependencies();
runApp(const MyApp());
}
Access the Service
Retrieve the registered service anywhere in your app.
final authService = getIt<AuthService>();
authService.login(
"john@example.com",
"password123",
);
Constructor Injection
Instead of creating services inside a class, inject them through the constructor.
class LoginController {
final AuthService authService;
LoginController(this.authService);
}
Create the controller like this:
final controller = LoginController(
getIt<AuthService>(),
);
Constructor injection improves maintainability and makes unit testing much easier.
Singleton vs Factory
Singleton
One shared instance for the entire application.
getIt.registerSingleton(
AuthService(),
);
Lazy Singleton
Creates the object only when it's first requested.
getIt.registerLazySingleton(
() => AuthService(),
);
Factory
Creates a new object every time.
getIt.registerFactory(
() => LoginController(
getIt<AuthService>(),
),
);
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



Top comments (0)