{"id":16352342,"url":"https://github.com/melbournedeveloper/flutter_ioc_container","last_synced_at":"2025-03-21T00:31:08.562Z","repository":{"id":62002075,"uuid":"557015263","full_name":"MelbourneDeveloper/flutter_ioc_container","owner":"MelbourneDeveloper","description":"A lightweight, flexible, and high-performance dependency injection and service location library for Flutter","archived":false,"fork":false,"pushed_at":"2024-06-30T23:51:37.000Z","size":386,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-20T15:58:25.079Z","etag":null,"topics":["dart","flutter","mobiledevelopment"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_ioc_container","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MelbourneDeveloper.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-24T23:50:41.000Z","updated_at":"2024-09-17T07:03:33.000Z","dependencies_parsed_at":"2024-02-01T04:24:34.474Z","dependency_job_id":"290b3e11-b9ef-4a15-a4ff-783d357ae0f0","html_url":"https://github.com/MelbourneDeveloper/flutter_ioc_container","commit_stats":{"total_commits":51,"total_committers":2,"mean_commits":25.5,"dds":"0.33333333333333337","last_synced_commit":"f35275ad8ba37ff9c6b3d6a8dcf7260e4d2c6c10"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MelbourneDeveloper%2Fflutter_ioc_container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MelbourneDeveloper%2Fflutter_ioc_container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MelbourneDeveloper%2Fflutter_ioc_container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MelbourneDeveloper%2Fflutter_ioc_container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MelbourneDeveloper","download_url":"https://codeload.github.com/MelbourneDeveloper/flutter_ioc_container/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244717361,"owners_count":20498282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter","mobiledevelopment"],"created_at":"2024-10-11T01:25:48.888Z","updated_at":"2025-03-21T00:31:08.164Z","avatar_url":"https://github.com/MelbourneDeveloper.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# flutter_ioc_container\n\n![ioc_container](https://github.com/MelbourneDeveloper/ioc_container/raw/main/images/ioc_container-256x256.png)\n\nManage your dependencies in the widget tree, access them from the `BuildContext`, and replace them with test doubles for testing.\n\n[ioc_container](https://pub.dev/packages/ioc_container) is a dependency injection and service location library for Dart. You can use it in Flutter as a service locator like the `GetIt` package. `flutter_ioc_container` is an extension for `ioc_container` that exposes the library throughout the widget tree so you can use it like `Provider`. It provides extension methods on `BuildContext` to allow you to get instances of your dependencies anywhere in the widget tree.\n\nThis accesses the `CounterController` to increment and grab the current value:\n\n```dart\nFloatingActionButton.extended(\n    icon: const Icon(Icons.add),\n    // Increment the value\n    onPressed: context\u003cCounterController\u003e().increment,\n    label: Text(\n    // Display the value\n    context\u003cCounterController\u003e().value.toString(),\n    style: Theme.of(context).textTheme.headlineMedium,\n    ),\n),\n```\n\n_See the [ioc_container](https://pub.dev/packages/ioc_container) documentation for a more comprehensive guide._\n\n## Getting Started\n\n### Installing the Package\n\nAdd the following line to your `pubspec.yaml` file under the dependencies section:\n\n```yaml\ndependencies:\n  flutter_ioc_container: \u003clatest version\u003e\n```\n\nRun `flutter pub get` to download the dependencies.\n\nOr, you can install the package from the command line:\n\n```sh\nflutter pub add flutter_ioc_container\n```\n\n### Basic Usage\n\n- Put a `CompositionRoot` widget at the base of your widget tree. This propagates the container throughout the widget tree as an inherited widget.\n- Specify the `configureBuild` parameter to configure the container.\n- Access the dependencies throughout the widget tree via the `BuildContext`.\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:flutter_ioc_container/flutter_ioc_container.dart';\n\nvoid main() {\n  runApp(\n    CompositionRoot.configureBuild(\n      MaterialApp(\n        home: Scaffold(\n          body: Builder(builder: (context) =\u003e const BasicWidget()),\n        ),\n      ),\n      (builder) =\u003e builder.addSingleton((container) =\u003e 'test'),\n    ),\n  );\n}\n\nclass BasicWidget extends StatelessWidget {\n  const BasicWidget({super.key});\n\n  @override\n  Widget build(BuildContext context) =\u003e Text(context\u003cString\u003e());\n}\n```\n\n### Scoping\n\nIf you need a set of dependencies that have a short life and you need to dispose of them afterward, something in the widget tree needs to hold onto a scoped container. Get a scoped container by calling `context.scoped()`. One approach is to put the scoped container in the `State` of a `StatefulWidget` and dispose of the contents in the `dispose()` method of the `State`.\n\nThis example creates a scoped container on `didChangeDependencies`. It exists for the lifespan of the state, and the resources get disposed when the widget tree disposes of this widget.\n\n```dart\nimport 'dart:async';\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_ioc_container/flutter_ioc_container.dart';\nimport 'package:ioc_container/ioc_container.dart';\n\nclass DisposableResources {\n  String display = 'hello world';\n\n  void dispose() {\n    // ignore: avoid_print\n    print('Disposed');\n  }\n}\n\nvoid main() {\n  runApp(\n    CompositionRoot.configureBuild(\n      MaterialApp(\n        home: Scaffold(\n          body: Builder(builder: (context) =\u003e const BasicWidget()),\n        ),\n      ),\n      (builder) =\u003e builder.add(\n        (container) =\u003e DisposableResources(),\n        dispose: (service) =\u003e service.dispose(),\n      ),\n    ),\n  );\n}\n\nclass BasicWidget extends StatefulWidget {\n  const BasicWidget({super.key});\n\n  @override\n  State\u003cBasicWidget\u003e createState() =\u003e _BasicWidgetState();\n}\n\nclass _BasicWidgetState extends State\u003cBasicWidget\u003e {\n  late final IocContainer scopedContainer;\n\n  @override\n  void didChangeDependencies() {\n    super.didChangeDependencies();\n    scopedContainer = context.scoped();\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    unawaited(scopedContainer.dispose());\n  }\n\n  @override\n  Widget build(BuildContext context) =\u003e\n      Text(scopedContainer\u003cDisposableResources\u003e().display);\n}\n```\n\nSee more on scoping [here](https://pub.dev/packages/ioc_container#scoping-and-disposal).\n\n### Async Injection\n\nIf your dependency requires async initialization, you can do this using `addAsync`. You can use the [`FutureBuilder`](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html) widget to render the object when it is available. Async singletons come with a [guarantee of no reentrancy](https://pub.dev/packages/ioc_container/versions/2.0.1-beta#v2-and-async-locking)(async locking), so it is safe to grab the singleton anywhere in the app and the future will resolve once.\n\n Here's an example:\n\n```dart\nimport 'dart:async';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_ioc_container/flutter_ioc_container.dart';\n\nvoid main() {\n  runApp(\n    CompositionRoot(\n      compose: BuildCompose(\n        (builder) =\u003e builder.addSingletonAsync(\n          (container) async =\u003e Future\u003cString\u003e.delayed(\n            const Duration(seconds: 5),\n            () =\u003e 'Hello world!',\n          ),\n        ),\n      ),\n      child: MaterialApp(\n        home: Scaffold(\n          body: Builder(builder: (context) =\u003e const BasicAsyncWidget()),\n        ),\n      ),\n    ),\n  );\n}\n\nclass BasicAsyncWidget extends StatefulWidget {\n  const BasicAsyncWidget({super.key});\n\n  @override\n  State\u003cBasicAsyncWidget\u003e createState() =\u003e _BasicAsyncWidgetState();\n}\n\nclass _BasicAsyncWidgetState extends State\u003cBasicAsyncWidget\u003e {\n  late final Future\u003cString\u003e future;\n\n  @override\n  void didChangeDependencies() {\n    // ignore: discarded_futures\n    future = context.getAsync\u003cString\u003e();\n    super.didChangeDependencies();\n  }\n\n  @override\n  Widget build(BuildContext context) =\u003e FutureBuilder(\n        // ignore: discarded_futures\n        future: future,\n        builder: (ctx, ss) =\u003e ss.connectionState == ConnectionState.done\n            ? Text(ss.data!)\n            : const CircularProgressIndicator(),\n      );\n}\n```\n\nSee more on async injection [here](https://pub.dev/packages/ioc_container#async-initialization).\n\n## Replace Dependencies with Test Doubles for Testing\n\nPass a `configureOverrides` function into your root widget. This allows you to replace dependencies with test doubles for testing. See the example widget [tests](example/test/widget_test.dart) for a full example.\n\n```dart\nclass MyApp extends StatelessWidget {\n  const MyApp({\n    super.key,\n    this.configureOverrides,\n  });\n\n  // This allows us to override the dependencies for testing. Take a look at\n  // the widget tests\n  final ConfigureBuild? configureOverrides;\n\n  @override\n  Widget build(BuildContext context) =\u003e CompositionRoot(\n        compose: BuildCompose(\n          configureOverrides: configureOverrides,\n          (builder) =\u003e builder\n            // Adds a singleton CounterController to the container\n            ..addSingleton(\n              (container) =\u003e CounterController(),\n            ),\n          // [...] See the example folder of this package for a full example\n        ),\n      );\n}\n```\n\nThis example overrides the dependency with a `MockValueNotifier`:\n\n```dart\ntestWidgets('Basic Smoke Test', (tester) async {\n    final mockValueNotifier = MockValueNotifier();\n\n    await tester.pumpWidget(\n      MyApp(\n        // This is how you substitute dependencies with test doubles\n        configureOverrides: (builder) =\u003e builder\n            .addSingleton\u003cCounterController\u003e((container) =\u003e mockValueNotifier),\n      ),\n    );\n\n    // Initial value\n    expect(find.text('0'), findsOneWidget);\n\n    // Tap the button\n    await tester.tap(find.byIcon(Icons.add));\n    await tester.pumpAndSettle();\n\n    // Verify value\n    expect(find.text('1'), findsOneWidget);\n    expect(find.text('0'), findsNothing);\n\n    // Ensure we're using the mock dependency\n    expect(mockValueNotifier.hasCalls, isTrue);\n  });\n```\n\nSee more on testing [here](https://pub.dev/packages/ioc_container#testing).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelbournedeveloper%2Fflutter_ioc_container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmelbournedeveloper%2Fflutter_ioc_container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelbournedeveloper%2Fflutter_ioc_container/lists"}