di_generator_build 1.2.0 copy "di_generator_build: ^1.2.0" to clipboard
di_generator_build: ^1.2.0 copied to clipboard

A powerful build runner package for automatic dependency injection code generation using GetIt in Flutter applications.

DI Generator Build #

A Flutter package that automatically generates dependency injection code for your classes using GetIt.

What This Package Does #

This package automatically creates dependency injection methods for any class you mark with the @AutoRegister annotation. It generates .g.dart files that contain methods to register and retrieve your classes from GetIt.

Key Benefit: Dependencies are only created and registered when you actually need them, not at startup!

How Lazy Loading Works #

Traditional Dependency Injection (Eager Loading): #

void main() {
  // โŒ All services created immediately at startup
  registerUserService();     // Creates UserService now
  registerProductService();  // Creates ProductService now  
  registerPaymentService();  // Creates PaymentService now
  // App starts slow, uses more memory from the beginning
}

With This Package (Lazy Loading): #

void main() {
  // โœ… No services created at startup - fast startup!
  // Services exist only when you actually request them
}

void showUserProfile() {
  // Only now is UserService created and registered
  final userService = getUserService(); // Created on-demand! ๐ŸŽฏ
  // ProductService and PaymentService still don't exist
}

void showProducts() {
  // Only now is ProductService created and registered
  final productService = getProductService(); // Created on-demand! ๐ŸŽฏ
}

Benefits of Lazy Loading #

  • ๐Ÿš€ Faster App Startup: No waiting for unused services to initialize
  • ๐Ÿ’พ Memory Efficient: Services exist only when needed
  • ๐ŸŽฏ On-Demand Creation: Dependencies created exactly when required
  • โšก Better Performance: App feels snappy and responsive
  • ๐Ÿ”„ Smart Resource Management: Resources allocated only when necessary

โœจ Features #

  • Intuitive Annotations: Use clear annotations like @Factory, @Singleton, @LazySingleton
  • Automatic Code Generation: Generates dependency injection methods automatically
  • GetIt Integration: Seamlessly integrates with the GetIt service locator
  • Async Support: Full support for async dependency initialization
  • Performance Optimized: Efficient dependency resolution with GetIt integration

๐Ÿš€ Quick Start #

1. Add Dependencies #

Add to your pubspec.yaml:

dependencies:
  get_it: ^7.6.0
  di_generator_build: ^1.0.0

dev_dependencies:
  build_runner: ^2.4.0

2. Use Annotations #

import 'package:di_generator_build/di_generator_build.dart';

part 'my_service.g.dart';

@Singleton()
class UserService {
  final UserRepository _repository;
  
  UserService(this._repository);
  
  Future<User> getUser(String id) async {
    return await _repository.findById(id);
  }
}

3. Run Code Generation #

dart run build_runner build
@LazySingleton()
class HeavyComputationService {
  // This service won't be instantiated until someone calls getHeavyComputationService()
  // Saves memory and startup time
}

@AsyncLazySingleton()
class DatabaseService {
  // Database connection won't be established until first use
  // Useful when you need runtime configuration
}

Factory & AsyncFactory #

  • New instance created every time
  • Perfect for services that should not share state
  • Useful for request-scoped services
@Factory()
class RequestLogger {
  // Each request gets its own logger instance
  // No shared state between requests
}

Singleton & AsyncSingleton #

  • Instance created immediately during registration
  • Use sparingly - only for services that must be available at startup
  • Good for configuration objects or lightweight services
@Singleton()
class AppConfig {
  // Configuration is loaded immediately
  // Available throughout app lifecycle
}

๐Ÿท๏ธ Available Annotations #

Synchronous Annotations #

Annotation Description Use Case
@Factory() Creates new instance each time Services that should not be shared
@Singleton() Creates instance immediately and reuses it Configuration objects, expensive services
@LazySingleton() Creates instance on first use, then reuses it Services with deferred initialization
@LazyFactory() Alias for LazySingleton Alternative naming convention

Asynchronous Annotations #

Annotation Description Use Case
@AsyncFactory() Creates new async instance each time Async services that should not be shared
@AsyncSingleton() Creates async instance immediately and reuses it Async services with immediate initialization
@AsyncLazySingleton() Creates async instance on first use Async services with deferred initialization

๐Ÿ“š Examples #

@LazySingleton()
class UserService {
  final UserRepository _repository;
  
  UserService(this._repository);
  
  Future<User> getUser(String id) async {
    return await _repository.findById(id);
  }
}

// UserService is only created when first accessed
// Saves memory and startup time
final userService = getUserService();

Service with Parameters #

@Factory()
class EmailService {
  final String _apiKey;
  final EmailProvider _provider;
  
  EmailService(this._provider, [this._apiKey = 'default-key']);
  
  Future<void> sendEmail(String to, String subject, String body) async {
    // Email sending logic
  }
}

// New instance created each time - no shared state
final emailService = getEmailService();

Async Lazy Service (Best for expensive operations) #

@AsyncLazySingleton()
class DatabaseService {
  final String _connectionString;
  late final Database _database;
  
  DatabaseService(this._connectionString);
  
  Future<void> initialize() async {
    _database = await Database.connect(_connectionString);
  }
  
  Future<QueryResult> query(String sql) async {
    return await _database.execute(sql);
  }
}

// Database connection only established when first needed
// Perfect for services that depend on runtime configuration
final dbService = await getDatabaseService();

Configuration Service (Use sparingly) #

@Singleton()
class AppConfig {
  final String apiUrl;
  final String apiKey;
  final bool debugMode;
  
  AppConfig({
    required this.apiUrl,
    required this.apiKey,
    this.debugMode = false,
  });
}

// Configuration loaded immediately at startup
// Only use for services that must be available immediately
final config = getAppConfig();

Memory-Efficient Service Chain #

@LazySingleton()
class AnalyticsService {
  final DatabaseService _db;
  final CacheService _cache;
  
  AnalyticsService(this._db, this._cache);
  
  Future<void> trackEvent(String event) async {
    // Heavy analytics processing
    // Only created when analytics are actually needed
  }
}

@LazySingleton()
class CacheService {
  // Cache service only initialized when first accessed
  // Saves memory if caching isn't used
}

// Services are created in dependency order only when needed
final analytics = getAnalyticsService();

โšก Performance Benefits #

Memory Optimization #

  • LazySingleton: Services consume memory only when accessed
  • Factory: No shared instances, perfect for request-scoped operations
  • AsyncLazySingleton: Expensive async operations deferred until needed

Startup Time Improvement #

  • No expensive initialization during app startup
  • Dependencies created on-demand
  • Faster app launch, especially for complex applications

Resource Management #

  • Database connections only established when needed
  • Heavy computations deferred until required
  • Network services initialized on first use

Best Practices for Performance #

// โœ… Good: Use LazySingleton for expensive services
@LazySingleton()
class ImageProcessingService {
  // Heavy image processing libraries loaded only when needed
}

// โœ… Good: Use Factory for stateless services
@Factory()
class LoggingService {
  // New instance each time, no shared state
}

// โš ๏ธ Use sparingly: Singleton for essential services only
@Singleton()
class AppConfig {
  // Only for services that must be available immediately
}

// โŒ Avoid: Don't use Singleton for expensive services
// @Singleton() // This loads immediately at startup
// class HeavyService { ... }

๐Ÿ”ง Generated Code #

The package automatically generates getter methods for each annotated class:

// For @Singleton() class UserService
UserService getUserService() {
  return GetIt.instance.getOrRegister<UserService>(
      () => UserService(getUserRepository()), RegisterAs.singleton);
}

// For @AsyncFactory() class DatabaseService
Future<DatabaseService> getDatabaseService({String connectionString = 'default'}) async {
  return await GetIt.instance.getOrRegisterAsync<DatabaseService>(
      () async => DatabaseService(connectionString), RegisterAs.factoryAsync);
}

๐Ÿ—๏ธ Architecture #

The package follows clean architecture principles and provides:

  • Annotation Layer: Intuitive annotations for dependency injection
  • Code Generation: Automatic generation of DI methods using build_runner
  • GetIt Integration: Seamless integration with GetIt service locator
  • Async Support: Full support for async dependency initialization
  • Performance Optimization: Efficient dependency resolution

๐Ÿ“ Project Structure #

lib/
โ”œโ”€โ”€ annotations.dart          # Dependency injection annotations
โ”œโ”€โ”€ builder.dart             # Code generation logic
โ”œโ”€โ”€ get_it_extension.dart    # GetIt extensions
โ””โ”€โ”€ di_generator_build.dart  # Main library exports

example/
โ”œโ”€โ”€ example.dart             # Comprehensive usage examples
โ””โ”€โ”€ example.g.dart          # Generated code (after build)

test/
โ””โ”€โ”€ di_generator_build_test.dart  # Unit tests

๐Ÿงช Testing #

Run the tests:

dart test

๐Ÿ” Code Generation #

The package uses build_runner for code generation. Generated files are placed alongside source files for better developer experience.

Build Commands #

# Generate code once
dart run build_runner build

# Watch for changes and generate automatically
dart run build_runner watch

# Clean generated files
dart run build_runner clean

๐Ÿค Contributing #

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Setup #

  1. Clone the repository
  2. Install dependencies: dart pub get
  3. Run tests: dart test
  4. Make your changes
  5. Submit a pull request

๐Ÿ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments #

๐Ÿ“ž Support #

If you have any questions or need help, please:

  1. Check the examples directory
  2. Review the tests for usage patterns
  3. Open an issue on GitHub
  4. Check the documentation

Happy coding! ๐ŸŽ‰

2
likes
0
points
43
downloads

Documentation

Documentation

Publisher

unverified uploader

Weekly Downloads

A powerful build runner package for automatic dependency injection code generation using GetIt in Flutter applications.

Repository (GitHub)
View/report issues

Topics

#dependency-injection #code-generation #build-runner #getit #flutter

License

unknown (license)

Dependencies

analyzer, build, get_it, source_gen

More

Packages that depend on di_generator_build