Accessing get_it Features
This guide shows how to access get_it features from within watch_it widgets. For detailed explanations of each get_it feature, see the get_it documentation.
Scopes with pushScope
get_it scopes create temporary registrations that are automatically cleaned up. Perfect for screen-specific state. See get_it Scopes for details.
pushScope() - Automatic Scope Management
pushScope() creates a scope when the widget mounts and automatically cleans it up on dispose:
class UserProfileScreen extends WatchingWidget {
@override
Widget build(BuildContext context) {
// Create scope on first build
pushScope(
init: (getIt) {
// Register screen-specific dependencies
getIt.registerLazySingleton<ProfileManager>(
() => ProfileManager(userId: '123'),
);
},
dispose: () {
// Optional cleanUp when the scope is popped when the widget gets disposed
print('Profile screen scope disposed');
},
);
// Use scoped dependencies
final profile = watchValue((ProfileManager m) => m.profile);
return YourUI();
}
}What happens:
- Widget builds first time → Scope is pushed,
initcallback runs - Dependencies registered in new scope
- Widget can watch scoped dependencies
- Widget disposes → Scope is automatically popped,
disposecallback runs
Use Case: Screen-Specific State
class ProductDetailScreen extends WatchingWidget {
final String productId;
ProductDetailScreen({required this.productId});
@override
Widget build(BuildContext context) {
pushScope(
init: (getIt) {
// Register screen-specific manager
getIt.registerLazySingleton<ProductDetailManager>(
() => ProductDetailManager(productId: productId),
);
},
);
final product = watchValue((ProductDetailManager m) => m.product);
final isLoading = watchValue((ProductDetailManager m) => m.isLoading);
if (isLoading) return CircularProgressIndicator();
return ProductDetailView(product: product);
}
}Named Instances
Watch specific named instances from get_it. See get_it Named Instances for registration details.
Watching Named Instances
class ApiMonitor extends WatchingWidget {
@override
Widget build(BuildContext context) {
// Watch specific named instances
final prodApi = watchValue(
(ApiClientExtended api) => api.requestCount,
instanceName: 'production',
);
final stagingApi = watchValue(
(ApiClientExtended api) => api.requestCount,
instanceName: 'staging',
);
return Column(
children: [
Text('Production: $prodApi requests'),
Text('Staging: $stagingApi requests'),
],
);
}
}Use cases:
- Multiple configurations (dev/prod)
- Feature flags
- A/B testing variants
Async Initialization
Handle complex initialization where async dependencies must be ready before the app starts. See get_it Async Objects for registration details.
isReady - Single Dependency
Check if a specific async dependency is ready:
void setupDependenciesAsync() async {
// Register async singleton
di.registerSingletonAsync<Database>(
() async {
final db = Database();
await db.initialize();
return db;
},
);
}
class App extends WatchingWidget {
@override
Widget build(BuildContext context) {
// Check if ready
final ready = isReady<Database>();
if (!ready) {
return SplashScreen();
}
return MainApp();
}
}allReady - Multiple Dependencies
Wait for all async dependencies to complete:
void setupMultipleDependencies() async {
di.registerSingletonAsync<Database>(() async {
final db = Database();
await db.initialize();
return db;
});
di.registerSingletonAsync<ConfigService>(() async {
final config = ConfigService();
await config.loadFromFile();
return config;
});
di.registerSingletonAsync<AuthServiceAdvanced>(
() async {
final auth = AuthServiceAdvanced();
await auth.initialize();
return auth;
},
dependsOn: [Database], // Waits for Database first
);
}
class AppAllReady extends WatchingWidget {
@override
Widget build(BuildContext context) {
// Wait for all async singletons
final ready = allReady(
timeout: Duration(seconds: 30),
onError: (context, error) {
// Handle timeout or initialization errors
// Without onError, exceptions would be thrown!
showErrorDialog(context, error);
},
);
if (!ready) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return MainApp();
}
}Error Handling
When using timeout, allReady() can throw WaitingTimeOutException if dependencies don't initialize in time. Additionally, if any async singleton's init function throws an exception, it propagates through allReady().
Use the onError callback to handle errors gracefully - otherwise exceptions will be thrown during widget build.
Alternative: watchFuture for Full Error Control
If you expect initialization errors and need full control via AsyncSnapshot, use watchFuture with di.allReady() directly:
class AppWithFullErrorHandling extends WatchingWidget {
@override
Widget build(BuildContext context) {
// watchFuture gives you an AsyncSnapshot for full error control
final snapshot = watchFuture<GetIt, void>(
(getIt) => getIt.allReady(timeout: Duration(seconds: 30)),
target: di,
initialValue: null,
);
if (snapshot.hasError) {
// Handle initialization errors (timeout or factory exceptions)
return ErrorScreen(error: snapshot.error);
}
if (snapshot.connectionState != ConnectionState.done) {
return SplashScreen();
}
return MainApp();
}
}When to use which:
allReady()withonError— simple cases, just need ready/not ready statewatchFuture(di.allReady())— when you need the fullAsyncSnapshot(hasError, error, connectionState)
Watching Initialization Progress
class InitializationScreen extends WatchingWidget {
@override
Widget build(BuildContext context) {
final dbReady = isReady<Database>();
final configReady = isReady<ConfigService>();
final authReady = isReady<AuthServiceAdvanced>();
final progress =
[dbReady, configReady, authReady].where((ready) => ready).length / 3;
if (dbReady && configReady && authReady) {
// All ready, navigate to main app
callOnceAfterThisBuild((context) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => MainApp()),
);
});
}
return Column(
children: [
LinearProgressIndicator(value: progress),
Text('Initializing... ${(progress * 100).toInt()}%'),
if (dbReady) Text('✓ Database ready'),
if (configReady) Text('✓ Configuration loaded'),
if (authReady) Text('✓ Authentication ready'),
],
);
}
}