D
OOP & SOLIDHard40 XP5 min read

What is dependency injection in Dart and how is it implemented?

TL;DR: DI provides dependencies from outside rather than creating them inside a class. GetIt is Flutter's go-to service locator. Flutter also supports constructor injection natively. DI enables testability (swap real with mock) and decoupling.

Full Answer

Without DI: UserService creates its own Dio() — impossible to test or swap. With DI: Dio is injected into UserService — swap with MockDio in tests.

Types of DI

  • Constructor injection — dependencies passed in constructor (preferred, most explicit)
  • Property injection — set after construction (less preferred, allows partially constructed objects)
  • Service locator (GetIt) — global registry; easy to use but hides dependencies (use sparingly)

GetIt Setup

GetIt is a simple service locator. Register singletons, factories, or lazy singletons. Access anywhere with GetIt.instance<T>(). Use injectable code generation to reduce boilerplate.

Code Examples

dartConstructor injection and GetIt
Output
// Constructor injection: dependencies visible, easy to test
// GetIt: convenient global access, watch for hidden coupling

Common Mistakes

  • Registering GetIt dependencies after they're first accessed — throws 'not registered' error at runtime
  • Using GetIt.instance everywhere instead of constructor injection — hides dependencies, harder to test

Interview Tip

💡

Prefer constructor injection for business logic (visible dependencies, testable). Use GetIt at the composition root (main.dart/app startup) to wire dependencies together. This is the professional pattern.

#dependency-injection#GetIt#service-locator#testability