depend is a library for dependency management in Flutter applications. It provides a convenient way to initialize and access services and repositories via InheritedWidget.
- Dependency Initialization: Prepare all dependencies before the app launches.
- Global Access: Access dependencies from anywhere in the widget tree.
- Parent Dependencies Support: Easily create nested or connected dependencies.
- Ease of Use: Integrate the library into existing code with minimal changes.
- Features π
- Table of Contents
- Installation
- Usage Examples
- Migration Guide
- Code Coverage
Add the library to the pubspec.yaml of your project:
dependencies:
depend: ^latest_versionInstall the dependencies:
flutter pub getCreate a class that extends DependencyContainer and initialize your dependencies:
class RootContainer extends DependencyContainer {
final ApiService apiService;
RootContainer({required this.apiService});
void dispose() {
apiService.dispose();
}
}Create a class that extends DependencyContainer and initialize your dependencies:
class RootDependencyFactory extends DependencyFactory<RootContainer> {
Future<RootContainer> create() async {
return RootContainer(
apiService: await ApiService.initialize(),
);
}
// or
RootContainer create() {
return RootContainer(
apiService: ApiService.initialize(),
);
}
}Wrap your app in a DependencyScope to provide dependencies:
void main() {
runApp(
DependencyScope<RootContainer, RootFactory>(
factory: RootFactory(),
placeholder: const Center(child: CircularProgressIndicator()),
builder: (BuildContext context) => const MyApp(),
),
);
}You can now access the dependency using DependencyProvider anywhere in the widget tree:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final apiService = DependencyProvider.of<RootContainer>(context).apiService;
return FutureBuilder(
future: apiService.getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Text('Data: ${snapshot.data}');
},
);
}
}final RootContainer dep = await RootFactory().create();
DependencyProvider<RootContainer>(
dependency: dep,
builder: () => YourWidget();
// or
child: YourWidget()
)
class YourWidget extends StatelessWidget {
@override
Widget build(BuildContext) {
root = DependencyProvider.of<RootContainer>(context);
...
}
}DependencyScope<RootContainer, RootFactory>(
factory: RootFactory(),
builder: (BuildContext context) => Text('Inject'),
placeholder: Text('Placeholder'),
errorBuilder: (Object? error) => Text('Error'),
),The library provides LazyGet and LazyFutureGet classes for lazy initialization of services. Dependencies are created only when they are first accessed, which improves application startup time.
class RootContainer extends DependencyContainer {
// Service will be created only when accessed for the first time
final LazyGet<ApiService> apiService = LazyGet(() => ApiService());
final LazyGet<DatabaseService> database = LazyGet(() => DatabaseService());
void dispose() {
// Check if the service was initialized before disposing
if (apiService._instance != null) {
apiService.instance.dispose();
}
}
}
// Usage in widgets
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final container = DependencyProvider.of<RootContainer>(context);
// ApiService is created only at this moment
final api = container.apiService.instance;
return Text('Service initialized: ${api.isReady}');
}
}class RootContainer extends DependencyContainer {
// Service with async initialization
final LazyFutureGet<DatabaseService> database =
LazyFutureGet(() async {
final db = DatabaseService();
await db.initialize();
return db;
});
final LazyFutureGet<AuthService> authService =
LazyFutureGet(() async => await AuthService.create());
}
// Usage in widgets
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final container = DependencyProvider.of<RootContainer>(context);
return FutureBuilder<DatabaseService>(
// Database is initialized only when this widget is built
future: container.database.instance,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
return Text('Database ready: ${snapshot.data?.isConnected}');
},
);
}
}Benefits of Lazy Initialization:
- Faster App Startup: Dependencies are created only when needed
- Memory Optimization: Unused services don't consume memory
- Flexible Initialization: You can control when heavy operations are performed
- Simple API: Easy to use with both sync and async dependencies

