Dependency injection has an intimidating name for an unremarkable idea: a class should be handed what it needs rather than constructing or locating it. That is the whole concept. Everything else — containers, locators, providers, generated code — is machinery for delivering it. The reason to care is testing. ApiClient() written inside a repository means every test of that repository makes real network calls. ApiClient passed in means every test can pass a fake. That is the entire payoff, and it is enough. Constructor injection, which needs no package final class UserRepository { const UserRepository ( this ._api, this ._cache); final ApiClient _api; final UserCache _cache; Future < User > fetch ( String id) async { final cached = _cache. get (id); if (cached != null ) return cached; final user = await _api. getUser (id); _cache. put (user); return user; } } Testing this requires no framework at all: test ( ...