bloomBUILD•SHIP•BLOOM
.md
Type-Safe IoC

Dependency Injection

Bloom includes an ultra-fast, zero-reflection dependency injection container (BloomContainer) supporting singletons, lazy factories, and hierarchical child scopes.

Registration Strategies

Register dependencies during boot with the registration strategy suited for your service lifecycle:

lib/app/boot.dart
dart
// lib/app/boot.dart
import 'package:bloom_framework/bloom.dart';
import '../services/analytics_service.dart';
import '../services/database_service.dart';
import '../features/auth/auth_controller.dart';

class AppBootstrapper implements BloomBootstrapper {
  @override
  Future<void> onBoot(BloomContainer container) async {
    // 1. Eager Singleton (Instantiated immediately at boot)
    container.provideSingleton<AnalyticsService>((c) => AnalyticsService());

    // 2. Lazy Singleton (Instantiated on first inject<T>() call)
    container.provideLazySingleton<DatabaseService>((c) => DatabaseService(
      analytics: c.inject<AnalyticsService>(),
    ));

    // 3. Factory (New instance created on every injection)
    container.provideFactory<AuthController>((c) => AuthController(
      db: c.inject<DatabaseService>(),
    ));
  }
}

Resolution with inject<T>()

Call inject<T>() from any controller, service, or widget:

Resolution Syntax
dart
// 1. Injection in Controllers / Services
class FeedController extends BloomController {
  final db = inject<DatabaseService>();
}

// 2. Injection in Flutter Widgets
class UserProfileWidget extends StatelessWidget {
  const UserProfileWidget({super.key});

  @override
  Widget build(BuildContext context) {
    // Resolved from root container
    final auth = inject<AuthController>();
    return Text(auth.user.value?.email ?? 'Guest');
  }
}

Hierarchical Scoped Containers

Spawn child containers for isolated flows (such as a checkout flow or tenant session) that can be disposed cleanly in a single call:

Scoped Container API
dart
// Child Scoped Container (e.g. for Modal / Flow lifetime)
final flowContainer = container.createChild();
flowContainer.provideSingleton<CheckoutSession>((c) => CheckoutSession());

// Disposing the scope tears down all scoped instances
flowContainer.dispose();