Dependency injection
The default DIPlugin uses an isolated GetIt container. Features register shared services during initialization and retrieve them by their declared type.
How the pieces fit together
Register and retrieve
import 'package:vyuh_core/vyuh_core.dart';
class CatalogStore {
String title = 'Catalog';
}
final feature = FeatureDescriptor(
name: 'catalog',
title: 'Catalog',
init: () async {
vyuh.di.register<CatalogStore>(CatalogStore());
},
dispose: () async {
if (vyuh.di.has<CatalogStore>()) {
vyuh.di.unregister<CatalogStore>();
}
},
routes: () => [],
);
// After feature initialization:
CatalogStore get catalogStore => vyuh.di.get<CatalogStore>();Use registerLazy to construct a shared instance on first access, or registerFactory to create a new instance per lookup. A named registration can distinguish two services with the same type.
Await asynchronous services
AsyncLazyDI.registerAsync<T> stores a lazy Future<T>; retrieve it with getAsync<T> and await completion. It does not turn an asynchronous dependency into a synchronous instance.
Own cleanup explicitly
The generic DIPlugin API has no disposer callback. Close subscriptions and owned resources before unregistering them. The default plugin resets its container at lifecycle boundaries; do not rely on container cleanup to implement domain-specific shutdown.
For state that belongs to a single screen, create and dispose it with the widget lifecycle or use your state management library’s scope. A feature that reads another feature’s registrations must declare that feature in dependencies.
See DIPlugin APIs, AsyncLazyDI, and startup ordering.