### Run Example App Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Navigate to the example directory and run the example application. Use 'cd ..' to return to the package root. ```bash cd example flutter run cd .. ``` -------------------------------- ### Define Installation Directories Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Sets variables for the installation paths of data and library files within the application bundle. ```cmake set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") ``` -------------------------------- ### GetIt Basic Setup and Registration Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Illustrates the basic setup of the GetIt instance and how to register lazy singletons and regular singletons. Also shows registering a singleton with dependencies. ```dart final getIt = GetIt.instance; void setupLocator() { // Register services getIt.registerLazySingleton(() => ApiService()); getIt.registerSingleton(ConfigService()); // Register with dependencies getIt.registerSingletonWithDependencies( () => AppModel(getIt()), dependsOn: [ApiService], ); } ``` -------------------------------- ### Install Application Executable Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs the main application executable to the runtime destination. This makes the application available for execution after the build process. ```cmake install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) ``` -------------------------------- ### Install Bundled Plugin Libraries Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Iterates through a list of bundled libraries and installs each one to the library directory of the application bundle. ```cmake foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) ``` -------------------------------- ### Setup Base Services with GetIt Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Registers base services like ApiClient and CacheManager as singletons. These services are intended to survive errors. ```dart // Base services (survive errors) void setupBaseServices() { di.registerSingleton(createApiClient()); di.registerSingleton(WcImageCacheManager()); } ``` -------------------------------- ### Install Bundled Plugin Libraries Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs any bundled plugin libraries to the application's root directory. This ensures that plugins are correctly deployed with the application. ```cmake if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Clean Build Bundle Directory on Install Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Installs a code block that recursively removes the build bundle directory before installation, ensuring a clean state. ```cmake install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) ``` -------------------------------- ### Install Flutter Library Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs the main Flutter library file to the application's root directory. This makes the core Flutter runtime available to the application. ```cmake install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Set Install Prefix for Bundled Application Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Configures the installation prefix to the build bundle directory by default, creating a relocatable application bundle. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() ``` -------------------------------- ### Two-Phase DI Setup with GetIt Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Implement a two-phase dependency injection strategy. First, set up base singletons, then push a new scope for services that might need to be reset or disposed, such as those tied to a user session. ```dart void setupBaseServices() { di.registerSingleton(createApiClient()); di.registerSingleton(WcImageCacheManager()); } Future setupThrowableScope() async { di.pushNewScope(scopeName: 'throwableScope'); di.registerLazySingletonAsync( () async => StoryManager().init(), dispose: (m) => m.dispose(), dependsOn: [UserManager], ); } ``` -------------------------------- ### Configure Installation Prefix for Bundled App Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Sets the installation prefix to be adjacent to the executable, facilitating in-place running and Visual Studio integration. This ensures that support files are correctly located relative to the application. ```cmake set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") ``` -------------------------------- ### Install Native Assets Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Installs native assets provided by the build.dart script from all packages into the library directory of the application bundle. ```cmake set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Testing with Scopes Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Use pushNewScope in setUp to register mocks that shadow real dependencies. Pop the scope in tearDown to clean up. ```dart // Option 1: Scope-based (preferred) - mocks shadow real registrations setUp(() { GetIt.I.pushNewScope( init: (getIt) { getIt.registerSingleton(MockApiClient()); }, ); }); tearDown(() async { await GetIt.I.popScope(); }); ``` -------------------------------- ### Install Get_it Dependency Source: https://github.com/flutter-it/get_it/blob/main/README.md Add the get_it package to your pubspec.yaml file to include it in your project dependencies. ```yaml dependencies: get_it: ^8.0.2 ``` -------------------------------- ### Install AOT Library for Release Builds Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compilation library to the data directory, but only for Profile and Release configurations. This optimizes performance for non-debug builds. ```cmake install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Install Native Assets Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs native assets provided by the build.dart script into the application's library directory. This ensures that all necessary native resources are included. ```cmake set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Find and check system-level dependencies Source: https://github.com/flutter-it/get_it/blob/main/example/linux/flutter/CMakeLists.txt This snippet uses PkgConfig to find and check for required system libraries like GTK, GLIB, and GIO. Ensure these libraries are installed on your system for the build to succeed. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) ``` -------------------------------- ### Setup Throwable Scope with GetIt Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Sets up a throwable scope that can be reset on errors. It registers a lazy singleton StoryManager that depends on UserManager. ```dart // Throwable scope (can be reset on errors) void setupThrowableScope() { di.pushNewScope(scopeName: 'throwable'); di.registerLazySingletonAsync( () async => StoryManager().init(), dispose: (m) => m.dispose(), dependsOn: [UserManager], ); } ``` -------------------------------- ### Install ICU Data File Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Installs the ICU data file to the data directory of the application bundle. This is necessary for internationalization support. ```cmake install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Install AOT Library for Non-Debug Builds Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compiled library to the application bundle's library directory, but only for non-Debug build configurations. ```cmake if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Install Flutter Assets Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Removes any existing Flutter assets and then copies the current Flutter assets to the application's data directory. This ensures that the assets are up-to-date. ```cmake set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Setup Mock ApiClient for Tests Source: https://github.com/flutter-it/get_it/blob/main/README.md In tests, register a mock ApiClient before running tests. Clear all registrations after each test to ensure isolation. ```dart setUp(() { getIt.registerSingleton(MockApiClient()); }); tearDown(() async { await getIt.reset(); }); ``` -------------------------------- ### get, call, maybeGet Source: https://context7.com/flutter-it/get_it/llms.txt `get()` and the callable shorthand `getIt()` retrieve a registered instance synchronously. `maybeGet()` returns `null` instead of throwing if the type is not registered. ```APIDOC ## get / call / maybeGet ### Description Retrieve registered instances synchronously. ### Method Signatures - `T get()` - `T call()` (shorthand for `get()`) - `T? maybeGet()` ### Parameters - **T** - The type of the instance to retrieve. ### Return Value - `get()` and `call()`: Returns an instance of type T. - `maybeGet()`: Returns an instance of type T, or null if not registered. ### Example ```dart final logger = getIt.get(); final loggerShorthand = getIt(); final loggerCall = getIt.call(); final missing = getIt.maybeGet(); ``` ``` -------------------------------- ### Global Exception Handler Setup Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Assign a static method to `Command.globalExceptionHandler` in `main()` to catch unhandled command errors. This handler provides a fallback for errors not caught by local listeners. ```dart // In TheApp static void globalErrorHandler(CommandError error, StackTrace stackTrace) { debugPrint('Command error [${error.commandName}]: ${error.error}'); di().showToast(error.error.toString(), isError: true); } // In main() Command.globalExceptionHandler = TheApp.globalErrorHandler; ``` -------------------------------- ### Registering an eager singleton with get_it Source: https://context7.com/flutter-it/get_it/llms.txt Use `registerSingleton` to register an already-created instance. The same object is returned on every `get()` call. An optional `dispose` callback can be provided for cleanup. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class DatabaseService { final String connectionString; DatabaseService(this.connectionString); Future close() async => print('DB closed'); @override String toString() => 'DatabaseService($connectionString)'; } void setup() { getIt.registerSingleton( DatabaseService('postgres://localhost/mydb'), dispose: (db) => db.close(), // called on unregister / reset ); } void main() { setup(); final db = getIt(); print(db); // DatabaseService(postgres://localhost/mydb) final db2 = getIt(); print(identical(db, db2)); // true — same instance } ``` -------------------------------- ### Set Minimum CMake Version and Project Name Source: https://github.com/flutter-it/get_it/blob/main/example/windows/CMakeLists.txt Specifies the minimum required CMake version and defines the project name. This is a standard starting point for CMake projects. ```cmake cmake_minimum_required(VERSION 3.14) project(get_it_example LANGUAGES CXX) ``` -------------------------------- ### Retrieve Registered Instances Synchronously Source: https://context7.com/flutter-it/get_it/llms.txt Use `get()`, the callable shorthand `getIt()`, or `getIt.call()` to retrieve registered instances synchronously. `maybeGet()` provides a safe way to retrieve an instance, returning `null` if the type is not registered, thus preventing runtime errors. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; abstract class Logger { void log(String message); } class ConsoleLogger implements Logger { @override void log(String message) => print('[LOG] $message'); } void setup() { getIt.registerSingleton(ConsoleLogger()); } void main() { setup(); // Three equivalent ways to retrieve: final a = getIt.get(); final b = getIt(); // callable class shorthand final c = getIt.call(); a.log('hello'); // [LOG] hello // Safe retrieval — returns null if not registered final missing = getIt.maybeGet(); print(missing); // null } ``` -------------------------------- ### Basic Get_it Usage: Register and Access Services Source: https://github.com/flutter-it/get_it/blob/main/README.md Demonstrates the three core steps of using get_it: defining services, registering them at app startup, and accessing them from anywhere in your application without needing BuildContext. ```dart import 'package:get_it/get_it.dart'; // Create a global instance (or use GetIt.instance) final getIt = GetIt.instance; // 1. Define your services class ApiClient { Future fetchData() async { /* ... */ } } class UserRepository { final ApiClient apiClient; UserRepository(this.apiClient); } // 2. Register them at app startup void configureDependencies() { getIt.registerSingleton( ApiClient()); getIt.registerLazySingleton( () => UserRepository(getIt()) ); } // 3. Access from anywhere in your app class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { // No BuildContext passing needed! getIt().apiClient.fetchData(); }, child: Text('Fetch Data'), ); } } ``` -------------------------------- ### GetIt Core Test Patterns Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Demonstrates common patterns for registering and retrieving factories and singletons, including verifying instance identity. Also shows how to register and check for async initialization readiness. ```dart // Test factory registration GetIt.I.registerFactory(() => MyClass()); expect(GetIt.I(), isA()); expect(GetIt.I(), isNot(same(GetIt.I()))); // Different instances // Test singleton registration final instance = MyClass(); GetIt.I.registerSingleton(instance); expect(GetIt.I(), same(instance)); // Same instance // Test async initialization GetIt.I.registerSingletonAsync(() async => MyService()); await GetIt.I.allReady(); expect(GetIt.I.isReadySync(), true); ``` -------------------------------- ### Async Initialization Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Explains the preferred pattern for asynchronous initialization of services using an `init()` method and `registerSingletonAsync`. ```APIDOC ## Async Initialization **Preferred pattern**: Give services a `Future init()` method that returns `this`. This keeps initialization logic inside the class and allows concise registration: ```dart class DatabaseService { late final Database _db; Future init() async { _db = await Database.open('app.db'); return this; // Always return this } } void configureDependencies() { // init() pattern - concise, self-contained initialization getIt.registerSingletonAsync( () => DatabaseService().init(), ); // With dependency ordering getIt.registerSingletonAsync( () => ApiClient().init(), dependsOn: [DatabaseService], ); // Sync factory that needs async dependencies getIt.registerSingletonWithDependencies( () => AppModel(getIt()), dependsOn: [ApiClient], ); } ``` ``` -------------------------------- ### Accessing the global instance Source: https://context7.com/flutter-it/get_it/llms.txt Demonstrates how to access the singleton instance of GetIt using `GetIt.instance` or `GetIt.I`, and how to create isolated instances for testing. ```APIDOC ## Accessing the global instance `GetIt` is a singleton. Access the shared global locator via `GetIt.instance` or the shorthand `GetIt.I`. For isolated contexts (e.g., testing modules), create a fresh instance with `GetIt.asNewInstance()`. ```dart import 'package:get_it/get_it.dart'; // Preferred: assign to a top-level variable for convenience final getIt = GetIt.instance; // Equivalent shorthand final sl = GetIt.I; // Isolated instance (useful for feature modules or tests) final moduleLocator = GetIt.asNewInstance(); ``` ``` -------------------------------- ### App Startup Configuration Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Sets up the Flutter application by ensuring bindings are initialized, dependencies are configured, and the main app widget is run. The splash screen handles asynchronous service loading before displaying the main application. ```dart void main() { WidgetsFlutterBinding.ensureInitialized(); configureDependencies(); // Register all services (sync) runApp(MyApp()); } // Splash screen waits for async services class SplashScreen extends WatchingWidget { @override Widget build(BuildContext context) { final ready = allReady( onReady: (context) => Navigator.pushReplacement(context, mainRoute), ); if (!ready) return CircularProgressIndicator(); return MainApp(); } } ``` -------------------------------- ### Register Services with get_it Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Demonstrates various registration methods for services in get_it, including singletons, lazy singletons, factories, and named instances. Ensure all services are registered before runApp(). ```dart final getIt = GetIt.instance; void configureDependencies() { // Singleton - created immediately getIt.registerSingleton(ApiClient()); // Singleton with dispose callback getIt.registerSingleton( StreamController(), dispose: (c) => c.close(), ); // Lazy singleton - created on first access getIt.registerLazySingleton(() => Database()); // Factory - new instance every call getIt.registerFactory(() => Logger()); // Factory with parameters getIt.registerFactoryParam( (tag, _) => Logger(tag), ); // Named instances - use when registering multiple instances of the same type getIt.registerSingleton(devConfig, instanceName: 'dev'); getIt.registerSingleton(prodConfig, instanceName: 'prod'); } ``` -------------------------------- ### GetIt Multiple Implementations Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Demonstrates how to enable and register multiple implementations of the same type, and how to retrieve all registered instances. This is useful for strategies or interchangeable components. ```dart // Enable feature first getIt.enableRegisteringMultipleInstancesOfOneType(); // Register multiple implementations getIt.registerLazySingleton(() => StripeProcessor()); getIt.registerLazySingleton(() => PayPalProcessor()); // Get all implementations final processors = getIt.getAll(); ``` -------------------------------- ### Service Registration Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Demonstrates various ways to register services with get_it, including singletons, lazy singletons, factories, and named instances. ```APIDOC ## Registration ```dart final getIt = GetIt.instance; void configureDependencies() { // Singleton - created immediately getIt.registerSingleton(ApiClient()); // Singleton with dispose callback getIt.registerSingleton( StreamController(), dispose: (c) => c.close(), ); // Lazy singleton - created on first access getIt.registerLazySingleton(() => Database()); // Factory - new instance every call getIt.registerFactory(() => Logger()); // Factory with parameters getIt.registerFactoryParam( (tag, _) => Logger(tag), ); // Named instances - use when registering multiple instances of the same type getIt.registerSingleton(devConfig, instanceName: 'dev'); getIt.registerSingleton(prodConfig, instanceName: 'prod'); } ``` ``` -------------------------------- ### Async Initialization with init() Pattern Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Illustrates the preferred pattern for asynchronous service initialization using an `init()` method within the service class. This pattern allows for concise registration and self-contained initialization logic. ```dart class DatabaseService { late final Database _db; Future init() async { _db = await Database.open('app.db'); return this; // Always return this } } void configureDependencies() { // init() pattern - concise, self-contained initialization getIt.registerSingletonAsync( () => DatabaseService().init(), ); // With dependency ordering getIt.registerSingletonAsync( () => ApiClient().init(), dependsOn: [DatabaseService], ); // Sync factory that needs async dependencies getIt.registerSingletonWithDependencies( () => AppModel(getIt()), dependsOn: [ApiClient], ); } ``` -------------------------------- ### Query Scope Information Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Check if a scope exists or get the name of the current scope. ```dart getIt.hasScope('user-session'); // bool getIt.currentScopeName; // String? ``` -------------------------------- ### get Source: https://context7.com/flutter-it/get_it/llms.txt Retrieves an instance of type T. If multiple instances of the same type are registered, `instanceName` must be provided. ```APIDOC ## Named instances — Multiple registrations of one type Pass `instanceName` to any registration or retrieval function to maintain multiple independent instances of the same type. ### Method `get({String? instanceName})` ### Parameters #### Type Parameters - **T**: The type of the instance to retrieve. #### Optional Parameters - **instanceName** (String): The name of the instance to retrieve if multiple instances of the same type are registered. ### Example ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class HttpClient { final String baseUrl; HttpClient(this.baseUrl); @override String toString() => 'HttpClient($baseUrl)'; } void setup() { getIt.registerSingleton( HttpClient('https://api.example.com'), instanceName: 'api', ); getIt.registerSingleton( HttpClient('https://cdn.example.com'), instanceName: 'cdn', ); } void main() { setup(); final api = getIt(instanceName: 'api'); final cdn = getIt(instanceName: 'cdn'); print(api); // HttpClient(https://api.example.com) print(cdn); // HttpClient(https://cdn.example.com) } ``` ``` -------------------------------- ### Run All Tests Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Execute all tests within the project. Use --verbose for detailed output. ```bash flutter test ``` ```bash flutter test --verbose ``` -------------------------------- ### Add Dependencies and Include Directories Source: https://github.com/flutter-it/get_it/blob/main/example/windows/runner/CMakeLists.txt Links necessary libraries (flutter, flutter_wrapper_app, dwmapi.lib) and adds the source directory to include paths. Application-specific dependencies should also be added here. ```cmake target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") ``` -------------------------------- ### registerFactory Source: https://context7.com/flutter-it/get_it/llms.txt Registers a factory function that creates a new instance every time `get()` is called. This is suitable for stateless services or short-lived objects. ```APIDOC ## registerFactory — Register a factory (new instance per call) Every call to `get()` invokes the factory and returns a fresh object. Ideal for stateless services, view models, or short-lived objects. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class SearchQuery { final List results = []; void execute(String query) => results.add('result_for_$query'); } void setup() { getIt.registerFactory(() => SearchQuery()); } void main() { setup(); final q1 = getIt(); final q2 = getIt(); print(identical(q1, q2)); // false — different instances q1.execute('flutter'); print(q1.results); // [result_for_flutter] print(q2.results); // [] — clean slate } ``` ``` -------------------------------- ### Publish Dry-Run Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Simulate a package publication to check for potential issues before actual publishing. ```bash flutter pub publish --dry-run ``` -------------------------------- ### registerSingleton Source: https://context7.com/flutter-it/get_it/llms.txt Registers an already-created instance as an eager singleton. The same object instance is returned on every `get()` call. Supports optional `dispose` callbacks and `signalsReady`. ```APIDOC ## registerSingleton — Register an eager singleton Registers an already-created instance. The same object is returned on every `get()` call. Optionally pass a `dispose` callback or set `signalsReady: true` to gate `allReady()` on manual readiness signalling. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class DatabaseService { final String connectionString; DatabaseService(this.connectionString); Future close() async => print('DB closed'); @override String toString() => 'DatabaseService($connectionString)'; } void setup() { getIt.registerSingleton( DatabaseService('postgres://localhost/mydb'), dispose: (db) => db.close(), // called on unregister / reset ); } void main() { setup(); final db = getIt(); print(db); // DatabaseService(postgres://localhost/mydb) final db2 = getIt(); print(identical(db, db2)); // true — same instance } ``` ``` -------------------------------- ### Test Setup with GetIt Reset Source: https://github.com/flutter-it/get_it/blob/main/CLAUDE.md Resets the GetIt service locator before each test to ensure a clean state. This is crucial for isolated and repeatable unit tests. ```dart void main() { setUp(() async { // Reset GetIt before each test await GetIt.I.reset(); }); test('description', () { // Test code }); } ``` -------------------------------- ### Avoid Accessing Async Services Before Ready Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Ensure all asynchronous dependencies are initialized using `allReady()` before accessing them to prevent runtime errors. ```dart // ❌ Accessing async service before allReady() configureDependencies(); final db = getIt(); // THROWS - not ready yet // ✅ Wait first await getIt.allReady(); final db = getIt(); // Safe ``` -------------------------------- ### resetLazySingleton / resetLazySingletons Source: https://context7.com/flutter-it/get_it/llms.txt Clears the stored instance of one or all lazy singletons so the factory is invoked again on the next get(). Useful for cache invalidation or test isolation within a scope. ```APIDOC ## `resetLazySingleton` / `resetLazySingletons` — Re-arm lazy singletons Clears the stored instance of one or all lazy singletons so the factory is invoked again on the next `get()`. Useful for cache invalidation or test isolation within a scope. ### Method - `resetLazySingleton({String? instanceName})` - `resetLazySingletons()` ### Parameters #### Type Parameters - **T**: The type of the lazy singleton to reset. #### Optional Parameters - **instanceName** (String): The name of the lazy singleton to reset if multiple instances of the same type are registered. ### Example ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class CacheService { final int version; CacheService(this.version); } int _version = 0; void setup() { getIt.registerLazySingleton(() => CacheService(++_version)); } void main() async { setup(); final c1 = getIt(); print(c1.version); // 1 await getIt.resetLazySingleton(); final c2 = getIt(); print(c2.version); // 2 — fresh instance print(identical(c1, c2)); // false } ``` ``` -------------------------------- ### Configure Cross-Building Sysroot Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Sets up the sysroot and find paths for cross-compiling Flutter applications. ```cmake if(FLUTTER_TARGET_PLATFORM_SYSROOT) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) endif() ``` -------------------------------- ### Registering a factory with get_it Source: https://context7.com/flutter-it/get_it/llms.txt Use `registerFactory` to register a function that creates a new instance every time `get()` is called. This is suitable for stateless services or short-lived objects. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class SearchQuery { final List results = []; void execute(String query) => results.add('result_for_$query'); } void setup() { getIt.registerFactory(() => SearchQuery()); } void main() { setup(); final q1 = getIt(); final q2 = getIt(); print(identical(q1, q2)); // false — different instances q1.execute('flutter'); print(q1.results); // [result_for_flutter] print(q2.results); // [] — clean slate } ``` -------------------------------- ### Implement WillSignalReady for Manual Ready Signalling Source: https://context7.com/flutter-it/get_it/llms.txt Implement WillSignalReady on a class to automatically mark it as requiring a manual ready signal. The `initialize` method kicks off async work and signals readiness. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class InitializableService implements WillSignalReady { bool isReady = false; void initialize() async { await Future.delayed(const Duration(milliseconds: 30)); isReady = true; getIt.signalReady(this); } } void setup() { final service = InitializableService(); getIt.registerSingleton(service); service.initialize(); // kicks off async work } void main() async { setup(); await getIt.allReady(); print(getIt().isReady); // true } ``` -------------------------------- ### UI Handles Loading State with allReady() Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Place `allReady()` in the UI (WatchingWidget) to manage the application's loading state. This ensures the UI displays a loading indicator until all asynchronous singletons are initialized. ```dart // ✅ UI handles loading state class MyApp extends WatchingWidget { @override Widget build(BuildContext context) { if (!allReady()) return LoadingScreen(); return MainApp(); } } ``` -------------------------------- ### Async Readiness Coordination with `allReady` and `isReady` Source: https://context7.com/flutter-it/get_it/llms.txt Coordinate asynchronous singleton readiness using `allReady()` for overall readiness or `isReady()` for specific types. Useful for splash screens in `FutureBuilder`. ```dart import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class StorageService { static Future init() async { await Future.delayed(const Duration(milliseconds: 100)); return StorageService(); } } class UserRepository { final StorageService storage; UserRepository(this.storage); } void setup() { getIt.registerSingletonAsync(() => StorageService.init()); getIt.registerSingletonAsync( () async => UserRepository(getIt()), dependsOn: [StorageService], ); } class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return FutureBuilder( future: getIt.allReady(timeout: const Duration(seconds: 10)), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return const Text('App ready'); } return const CircularProgressIndicator(); }, ); } } ``` -------------------------------- ### Find PkgConfig and GTK+ 3.0 Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Finds the PkgConfig tool and checks for the GTK+ 3.0 library, making its imported target available. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) ``` -------------------------------- ### Retrieving Services from get_it Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Shows different methods for retrieving registered services from the get_it locator, including synchronous and asynchronous retrieval, handling missing instances, accessing named instances, and using factory parameters. ```dart final api = getIt(); // get() - throws if missing final api = getIt.maybeGet(); // returns null if missing final api = await getIt.getAsync(); // waits for async registration final all = getIt.getAll(); // all instances of type final config = getIt(instanceName: 'dev'); // named instance final logger = getIt(param1: 'MyClass'); // factory with params ``` -------------------------------- ### Apply Standard Build Settings Source: https://github.com/flutter-it/get_it/blob/main/example/linux/runner/CMakeLists.txt Applies a standard set of build settings to the application target. This can be customized or removed if the application requires different build configurations. ```cmake apply_standard_settings(${BINARY_NAME}) ``` -------------------------------- ### Manager init() vs Commands Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Distinguish between Manager init() for direct API calls and Commands for UI-facing reactive interfaces. Manager init() should load initial data without involving commands. ```dart class MyManager { final items = ValueNotifier>([]); // Command for UI-triggered refresh (widget watches isRunning) late final loadCommand = Command.createAsyncNoParam>( () async { final result = await di().getItems(); items.value = result; return result; }, initialValue: [], ); // init() calls API directly — no command needed Future init() async { items.value = await di().getItems(); return this; } } ``` -------------------------------- ### Proxy with Smart Fallbacks for Async Data Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Handles cases where full data is loaded asynchronously. Getters provide fallbacks to initial lightweight data (`SearchItem`) if the full data (`Podcast`) is not yet available. Includes a fetch command to load the full data and episodes. ```dart class PodcastProxy extends ChangeNotifier { PodcastProxy({required this.item}); final SearchItem item; // Initial lightweight data Podcast? _podcast; // Full data loaded later List? _episodes; // Getters fall back to initial data if full data not yet loaded String? get title => _podcast?.title ?? item.collectionName; String? get image => _podcast?.image ?? item.bestArtworkUrl; late final fetchCommand = Command.createAsyncNoParam>( () async { if (_episodes != null) return _episodes!; // Cache final result = await di().findEpisodes(item: item); _podcast = result.podcast; _episodes = result.episodes; return _episodes!; }, initialValue: [], ); } ``` -------------------------------- ### allReady / allReadySync / isReady / isReadySync Source: https://context7.com/flutter-it/get_it/llms.txt Provides mechanisms for asynchronous readiness coordination. `allReady()` returns a `Future` that completes when all async singletons and `signalsReady: true` singletons are ready. `isReady()` checks readiness for a single type. ```APIDOC ## allReady / allReadySync / isReady / isReadySync ### Description `allReady()` returns a `Future` that completes when all async singletons and `signalsReady: true` singletons are ready. Use in `FutureBuilder` for splash screens. `isReady()` checks readiness for a single type. ### Method Signatures - `Future allReady({Duration? timeout}) - `bool allReadySync()` - `bool isReady()` - `bool isReadySync()` ### Usage Example ```dart import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class StorageService { static Future init() async { await Future.delayed(const Duration(milliseconds: 100)); return StorageService(); } } class UserRepository { final StorageService storage; UserRepository(this.storage); } void setup() { getIt.registerSingletonAsync(() => StorageService.init()); getIt.registerSingletonAsync( () async => UserRepository(getIt()), dependsOn: [StorageService], ); } class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return FutureBuilder( future: getIt.allReady(timeout: const Duration(seconds: 10)), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return const Text('App ready'); } return const CircularProgressIndicator(); }, ); } } ``` ``` -------------------------------- ### Push and Pop Scopes (Asynchronous) Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Use pushNewScopeAsync for asynchronous initialization. Ensure to await the popScope() call as it handles dispose callbacks. ```dart await getIt.pushNewScopeAsync( scopeName: 'user-session', init: (getIt) async { final prefs = await UserPrefs.load(currentUser.id); getIt.registerSingleton(prefs); }, ); await getIt.popScope(); ``` -------------------------------- ### get_it Scopes for Mocking Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Utilize get_it scopes for setting up mock dependencies during testing. Push a new scope to register mock singletons and pop the scope to clean up afterwards. ```dart // Option 1: get_it scopes for mocking setUp(() { GetIt.I.pushNewScope( init: (getIt) { getIt.registerSingleton(MockApiClient()); }, ); }); tearDown(() async { await GetIt.I.popScope(); }); ``` -------------------------------- ### Manual Readiness Signalling with `signalReady` Source: https://context7.com/flutter-it/get_it/llms.txt Manually signal readiness for singletons registered with `signalsReady: true` by calling `GetIt.instance.signalReady(this)`. This unblocks `allReady()`. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class BackgroundWorker { BackgroundWorker() { _startWork(); } void _startWork() async { await Future.delayed(const Duration(milliseconds: 50)); print('Worker done, signalling ready'); getIt.signalReady(this); // manually unblocks allReady() } } void setup() { getIt.registerSingleton( BackgroundWorker(), signalsReady: true, ); } void main() async { setup(); await getIt.allReady(); print('All services ready'); // printed after worker signals } ``` -------------------------------- ### Correct Usage of Push Scope Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Use `pushNewScope` for synchronous initialization and `pushNewScopeAsync` for asynchronous initialization. Do not `await` `pushNewScope` as it returns `void`. ```dart // ❌ await on pushNewScope (it's void, not Future) await getIt.pushNewScope(scopeName: 'x'); // Won't compile // ✅ Use pushNewScopeAsync for async init await getIt.pushNewScopeAsync( scopeName: 'x', init: (getIt) async { ... }, ); // OR use synchronous pushNewScope without await getIt.pushNewScope(scopeName: 'x', init: (getIt) { ... }); ``` -------------------------------- ### registerSingletonWithDependencies Source: https://context7.com/flutter-it/get_it/llms.txt Creates a synchronous singleton only after its listed `dependsOn` types are all ready. ```APIDOC ## registerSingletonWithDependencies ### Description Creates a synchronous singleton only after its listed `dependsOn` types are all ready. ### Method Signature `void registerSingletonWithDependencies(FactoryFunc factory, {Iterable dependsOn}) ` ### Parameters - **factory** (FactoryFunc) - A function that creates the instance of type T. - **dependsOn** (Iterable) - An optional list of types that must be ready before this singleton is created. ### Example ```dart getIt.registerSingletonWithDependencies( () => AuthService(getIt().token), dependsOn: [TokenStore], ); ``` ``` -------------------------------- ### Wait for All Asynchronous Registrations Source: https://github.com/flutter-it/get_it/blob/main/skills/get-it-expert/SKILL.md Use allReady to wait for all asynchronous service initializations to complete, with an optional timeout. ```dart await getIt.allReady(timeout: Duration(seconds: 10)); ``` -------------------------------- ### pushNewScopeAsync Source: https://context7.com/flutter-it/get_it/llms.txt An asynchronous version of `pushNewScope`. The `init` callback is asynchronous, allowing async registrations to complete before the scope becomes active. ```APIDOC ## pushNewScopeAsync ### Description Like `pushNewScope` but the `init` callback is asynchronous, allowing async registrations to complete before the scope is considered active. ### Method Signature `Future pushNewScopeAsync({required String scopeName, required Future Function(GetIt) init, Function? dispose})` ### Usage Example ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class TenantConfig { final String tenantId; TenantConfig(this.tenantId); } void main() async { await getIt.pushNewScopeAsync( scopeName: 'tenant', init: (g) async { await Future.delayed(const Duration(milliseconds: 20)); // simulate fetch g.registerSingleton(TenantConfig('acme-corp')); }, ); print(getIt().tenantId); // acme-corp await getIt.popScope(); } ``` ``` -------------------------------- ### Create User Session Scope with GetIt Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Creates a new scope for a user session, registering the User object and UserPrefs. This scope is typically created at login. ```dart // User session scope (created at login, destroyed at logout) void createUserSession(User user) { di.pushNewScope( scopeName: 'user-session', init: (getIt) { getIt.registerSingleton(user); getIt.registerLazySingleton(() => UserPrefs(user.id)); }, ); } ``` -------------------------------- ### Initialize GetIt in Flutter Widget Previews Source: https://github.com/flutter-it/get_it/blob/main/README.md When using Flutter's widget previewer, initialize get_it within the preview function itself. This ensures that dependencies are available for the preview. Consider using a wrapper for automatic cleanup. ```dart @Preview() Widget myPreview() { if (!getIt.isRegistered()) { getIt.registerSingleton(MockService()); } return const MyWidget(); } ``` ```dart @Preview(name: 'My Widget', wrapper: myWrapper) Widget myPreview() => const MyWidget(); ``` -------------------------------- ### Set Include Directories Source: https://github.com/flutter-it/get_it/blob/main/example/linux/runner/CMakeLists.txt Configures the include directories for the application target, making source files accessible during compilation. ```cmake target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") ``` -------------------------------- ### Manager Pattern Implementation Source: https://github.com/flutter-it/get_it/blob/main/skills/flutter-architecture-expert/SKILL.md Demonstrates the Manager pattern for encapsulating business logic, using `ChangeNotifier` for state management and `Command` for asynchronous operations. It includes registration with `get_it` and usage within a widget. ```dart class UserManager extends ChangeNotifier { final _userState = ValueNotifier(UserState.loggedOut); ValueListenable get userState => _userState; late final loginCommand = Command.createAsync( (request) async { final api = di(); return await api.login(request); }, initialValue: User.empty(), errorFilter: const GlobalIfNoLocalErrorFilter(), ); late final logoutCommand = Command.createAsyncNoParamNoResult( () async { await di().logout(); }, ); void dispose() { /* cleanup */ } } // Register di.registerLazySingleton( () => UserManager(), dispose: (m) => m.dispose(), ); // Use in widget class LoginWidget extends WatchingWidget { @override Widget build(BuildContext context) { final isRunning = watch(di().loginCommand.isRunning).value; registerHandler( select: (UserManager m) => m.loginCommand.errors, handler: (context, error, _) { showErrorSnackbar(context, error.error); }, ); return ElevatedButton( onPressed: isRunning ? null : () => di().loginCommand.run(request), child: isRunning ? CircularProgressIndicator() : Text('Login'), ); } } ``` -------------------------------- ### Register Async Singleton with Dependencies Source: https://context7.com/flutter-it/get_it/llms.txt Register an asynchronous singleton using `registerSingletonAsync`. The factory is an async function that creates the instance in the background. Use `dependsOn` to specify initialization order for dependent services. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class ConfigService { late final Map config; static Future load() async { await Future.delayed(const Duration(milliseconds: 50)); // simulate I/O return ConfigService()..config = {'apiUrl': 'https://api.example.com'}; } } class ApiClient { final String baseUrl; ApiClient(this.baseUrl); } void setup() { getIt.registerSingletonAsync(() => ConfigService.load()); // ApiClient depends on ConfigService being ready first getIt.registerSingletonAsync( () async { final cfg = await getIt.getAsync(); return ApiClient(cfg.config['apiUrl']!); }, dependsOn: [ConfigService], ); } void main() async { setup(); // Wait for all async singletons to be ready await getIt.allReady(timeout: const Duration(seconds: 5)); final client = getIt(); print(client.baseUrl); // https://api.example.com } ``` -------------------------------- ### Asynchronous Scope Initialization with `pushNewScopeAsync` Source: https://context7.com/flutter-it/get_it/llms.txt Initialize new scopes asynchronously using `pushNewScopeAsync`. The `init` callback can perform async operations before the scope is considered active. ```dart import 'package:get_it/get_it.dart'; final getIt = GetIt.instance; class TenantConfig { final String tenantId; TenantConfig(this.tenantId); } void main() async { await getIt.pushNewScopeAsync( scopeName: 'tenant', init: (g) async { await Future.delayed(const Duration(milliseconds: 20)); // simulate fetch g.registerSingleton(TenantConfig('acme-corp')); }, ); print(getIt().tenantId); // acme-corp await getIt.popScope(); } ``` -------------------------------- ### Set Runtime Path for Bundled Libraries Source: https://github.com/flutter-it/get_it/blob/main/example/linux/CMakeLists.txt Configures the runtime search path to include bundled libraries from the 'lib/' directory relative to the binary. ```cmake set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") ```