levit_di 0.0.3
levit_di: ^0.0.3 copied to clipboard
Pure Dart dependency injection and service locator. Part of the Levit framework.
levit_di #
Type-safe, hierarchical dependency injection for Dart. Explicit. Scoped. Deterministic.
levit_di is a pure Dart dependency injection and service registry designed for applications that require predictable lifecycles, explicit scoping, and type safety. It provides a minimal but powerful set of primitives for managing services and controllers across both UI and non-UI Dart environments.
It is framework-agnostic by design and can be used standalone, or as the dependency backbone of the broader Levit ecosystem.
Note For Flutter applications, use
levit_flutter, which includes this package and integrates it with the widget tree.
Features #
-
Simple, Explicit API Register with
Levit.put, retrieve withLevit.find. No annotations or code generation. -
Lazy Initialization
Levit.lazyPutdefers instantiation until the dependency is first requested. -
Async-First Registration
Levit.putAsyncguarantees that asynchronous dependencies are fully initialized before use. -
Hierarchical Scoping Create isolated dependency graphs using named or anonymous scopes.
-
Deterministic Lifecycle Management Automatic invocation of
onInitandonDisposehooks for managed services. -
Pure Dart, Zero UI Coupling Usable in servers, CLI tools, tests, and shared libraries.
Installation #
dependencies:
levit_di: ^latest
import 'package:levit_di/levit_di.dart';
Quick Start #
Registering Dependencies #
// Eager registration
Levit.put(AuthService());
// Lazy registration (factory)
// The instance is created only when first requested.
Levit.lazyPut(() => Database());
// Async registration
// Calls are suspended until the Future completes.
await Levit.putAsync(() => ConfigService.load());
Retrieving Dependencies #
// Available anywhere in your Dart code
final auth = Levit.find<AuthService>();
auth.login();
Dependency resolution is synchronous once registration has completed.
Scoped Dependency Graphs #
Levit supports hierarchical scopes, allowing you to model feature- or lifecycle-bound dependencies explicitly.
// Create an isolated child scope
final checkoutScope = Levit.createScope('checkout');
// Register dependencies within this scope only
checkoutScope.put(PaymentProcessor());
// Resolve from the same scope
final processor = checkoutScope.find<PaymentProcessor>();
// Dispose the scope and all contained dependencies
checkoutScope.dispose();
Scopes enable clear ownership and predictable teardown of resources.
Lifecycle Management #
Services can opt into lifecycle hooks by implementing LevitDisposable.
class MyService implements LevitDisposable {
@override
void onInit() {
print('Service initialized');
}
@override
void onDispose() {
print('Service releasing resources');
}
}
The container guarantees that:
onInitis called exactly once after creationonDisposeis called when the service is removed or its scope is destroyed
This makes resource management explicit and testable.
When to Use levit_di #
Use levit_di directly when you need:
- A lightweight, type-safe service locator
- Explicit lifecycle and scope control
- Dependency management outside of Flutter
For reactive state and derived values, pair it with levit_reactive.
For Flutter widget integration, add levit_flutter.
Design Philosophy #
levit_di favors:
- Explicitness over hidden behavior
- Deterministic lifecycles over global singletons
- Composability over framework lock-in
It provides the minimum surface area required to manage dependencies correctly—no more, no less.