get_it_lazyload 0.0.3
get_it_lazyload: ^0.0.3 copied to clipboard
A Flutter package providing optimized lazy loading extensions for GetIt dependency injection with comprehensive support for all registration types and async dependencies.
get_it_lazyload #
A Flutter package providing optimized lazy loading extensions for GetIt dependency injection with comprehensive support for all registration types and async dependencies.
β¨ Features #
- π Optimized Lazy Loading: Efficient dependency registration with automatic instance creation
- π Multiple Registration Types: Support for factory, singleton, and lazy singleton patterns
- β‘ Async Support: Full support for asynchronous dependency initialization
- π― Performance Optimized: Minimal overhead with smart registration checking
- π‘οΈ Type Safe: Full type safety with generic methods
- π§ͺ Well Tested: 100% test coverage ensuring reliability
π¦ Installation #
Add this to your package's pubspec.yaml
file:
dependencies:
get_it_lazyload: ^0.0.3
get_it: ^8.2.0
Then run:
flutter pub get
π Quick Start #
import 'package:get_it/get_it.dart';
import 'package:get_it_lazyload/get_it_lazyload.dart';
final getIt = GetIt.instance;
// Register a service with automatic lazy loading
final service = getIt.getOrRegister<MyService>(
() => MyService(),
RegisterAs.singleton
);
π Usage #
Basic Usage #
import 'package:get_it/get_it.dart';
import 'package:get_it_lazyload/get_it_lazyload.dart';
final getIt = GetIt.instance;
// Register a service with automatic lazy loading
getIt.getOrRegister<MyService>(() => MyService(), RegisterAs.singleton);
// Get the service (will be created if not registered)
final service = getIt.get<MyService>();
Lazy Loading Pattern for Use Cases and Repositories #
The main benefit of this package is avoiding eager registration of dependencies at app startup. Instead, dependencies are loaded and registered only when they're actually required:
// UseCase with Factory pattern (creates new instance each time)
class AnonymousAuthUseCase {
final AuthRepository _repository;
AnonymousAuthUseCase(this._repository);
Future<FirebaseUserModel> execute() {
return _repository.signInAnonymously();
}
static AnonymousAuthUseCase get() {
return GetIt.instance.getOrRegister<AnonymousAuthUseCase>(
() => AnonymousAuthUseCase(AuthRepository.get()),
RegisterAs.factory);
}
}
// Repository with LazySingleton pattern (reuses instance)
class AuthRepository {
final DatabaseService _database;
AuthRepository(this._database);
Future<FirebaseUserModel> signInAnonymously() async {
return _database.createAnonymousUser();
}
static AuthRepository get() {
return GetIt.instance.getOrRegister<AuthRepository>(
() => AuthRepository(DatabaseService.get()),
RegisterAs.lazySingleton);
}
}
// Service with Singleton pattern (created immediately when first accessed)
class DatabaseService {
static DatabaseService get() {
return GetIt.instance.getOrRegister<DatabaseService>(
() => DatabaseService(),
RegisterAs.singleton);
}
}
Benefits of this pattern:
- β Dependencies are created only when needed
- β No eager registration at app startup
- β Automatic dependency resolution
- β Clean separation of concerns
- β Easy to test and mock
Registration Types #
Singleton
Creates instance immediately and reuses it:
getIt.getOrRegister<ConfigService>(
() => ConfigService(),
RegisterAs.singleton
);
Factory
Creates new instance each time:
getIt.getOrRegister<DataModel>(
() => DataModel(),
RegisterAs.factory
);
Lazy Singleton
Creates instance on first use, then reuses it:
getIt.getOrRegister<ExpensiveService>(
() => ExpensiveService(),
RegisterAs.lazySingleton
);
Async Dependencies #
Async Factory
final service = await getIt.getOrRegisterAsync<AsyncService>(
() async => await AsyncService.initialize(),
RegisterAs.factoryAsync
);
Async Lazy Singleton
final service = await getIt.getOrRegisterAsync<AsyncService>(
() async => await AsyncService.initialize(),
RegisterAs.lazySingletonAsync
);
Async Singleton
final service = await getIt.getOrRegisterAsync<AsyncService>(
() async => await AsyncService.initialize(),
RegisterAs.singletonAsync
);
Convenience Methods #
For common use cases, you can use these convenience methods:
// Factory registration
getIt.getOrRegisterFactory<DataModel>(() => DataModel());
// Lazy singleton registration
getIt.getOrRegisterLazySingleton<Service>(() => Service());
// Singleton registration
getIt.getOrRegisterSingleton<Config>(() => Config());
// Async variants
await getIt.getOrRegisterFactoryAsync<AsyncService>(
() async => await AsyncService.initialize()
);
await getIt.getOrRegisterLazySingletonAsync<AsyncService>(
() async => await AsyncService.initialize()
);
await getIt.getOrRegisterSingletonAsync<AsyncService>(
() async => await AsyncService.initialize()
);
π API Reference #
RegisterAs Enum #
RegisterAs.singleton
- Creates instance immediately and reuses itRegisterAs.factory
- Creates new instance each timeRegisterAs.lazySingleton
- Creates instance on first use, then reuses itRegisterAs.factoryAsync
- Creates new async instance each timeRegisterAs.lazySingletonAsync
- Creates async instance on first use, then reuses itRegisterAs.singletonAsync
- Creates async instance immediately and reuses it
GetItExtension Methods #
getOrRegister<T>()
- Gets or registers a dependencygetOrRegisterAsync<T>()
- Gets or registers an async dependencygetOrRegisterFactory<T>()
- Gets or registers as factorygetOrRegisterLazySingleton<T>()
- Gets or registers as lazy singletongetOrRegisterSingleton<T>()
- Gets or registers as singletongetOrRegisterFactoryAsync<T>()
- Gets or registers as async factorygetOrRegisterLazySingletonAsync<T>()
- Gets or registers as async lazy singletongetOrRegisterSingletonAsync<T>()
- Gets or registers as async singleton
π Performance Benefits #
- Single Registration Check: Only checks if dependency is registered once per call
- Optimized Registration: Direct function registration without extra wrapping
- Lazy Initialization: Dependencies are only created when needed
- Memory Efficient: Reuses instances where appropriate
- Startup Performance: No eager registration means faster app startup
β οΈ Important Notes #
Async Registration Behavior #
Due to GetIt's internal implementation of async registrations, there are some limitations to be aware of:
- Async Factory: Works as expected - creates new instances each time
- Async Lazy Singleton: May create new instances on subsequent calls due to GetIt's async registration behavior
- Async Singleton: Works as expected - creates instance once and reuses it
For the most reliable behavior with async dependencies, consider using RegisterAs.singletonAsync
when you need consistent instance reuse.
Best Practices #
- Use sync registration methods when possible for better performance
- Reserve async registration for dependencies that truly require async initialization
- Test your dependency injection setup thoroughly, especially with async services
- Consider using
RegisterAs.singletonAsync
for services that should be shared across your app - Use the lazy loading pattern for UseCases and Repositories to avoid eager registration
- Only register core dependencies (like config) at app startup
π± Example #
Check out the example app for a complete working demonstration of the lazy loading pattern.
import 'package:get_it/get_it.dart';
import 'package:get_it_lazyload/get_it_lazyload.dart';
class MyApp {
static void setupDependencies() {
final getIt = GetIt.instance;
// Only register core dependencies that are needed immediately
getIt.getOrRegister<ConfigService>(
() => ConfigService(),
RegisterAs.singleton
);
// Other dependencies will be registered lazily when first accessed
// No need to register AuthRepository, AnonymousAuthUseCase, etc. here
}
}
π§ͺ Testing #
The package includes comprehensive tests with 100% coverage:
# Run tests
flutter test
# Run tests with coverage
flutter test --coverage
π€ Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π Acknowledgments #
- Built on top of the excellent GetIt package
- Inspired by clean architecture principles and dependency injection best practices
- Community feedback and contributions
π Package Health #
- β Test Coverage: 100%
- β Static Analysis: Passing
- β Documentation: Complete
- β Examples: Included
- β License: MIT
- β Platform Support: Flutter (iOS, Android, Web, Desktop)