From 8f980ff11151f3df603fc4d5ae8331c5c650f41d Mon Sep 17 00:00:00 2001 From: Sergey Penkovsky Date: Mon, 11 Aug 2025 12:02:32 +0300 Subject: [PATCH] docs(readme): add detailed section and examples for automatic Disposable resource cleanup\n\n- Added a dedicated section with English description and code samples on using Disposable for automatic resource management.\n- Updated Features to include automatic resource cleanup for Disposable dependencies.\n\nHelps developers understand and implement robust DI resource management practices. --- cherrypick/README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/cherrypick/README.md b/cherrypick/README.md index 7af6a6c..ebc5521 100644 --- a/cherrypick/README.md +++ b/cherrypick/README.md @@ -86,6 +86,59 @@ await CherryPick.closeRootScope(); // await rootScope.dispose(); ``` +--- + +### Automatic Resource Cleanup with Disposable + +CherryPick can automatically clean up any dependency that implements the `Disposable` interface. This makes resource management (for controllers, streams, sockets, files, etc.) easy and reliable—especially when scopes or the app are shut down. + +If you bind an object implementing `Disposable` as a singleton or provide it via the DI container, CherryPick will call its `dispose()` method when the scope is closed or cleaned up. + +#### Key Points +- Supports both synchronous and asynchronous cleanup (dispose may return `void` or `Future`). +- All `Disposable` instances from the current scope and subscopes will be disposed in the correct order. +- Prevents resource leaks and enforces robust cleanup. +- No manual wiring needed once your class implements `Disposable`. + +#### Minimal Sync Example +```dart +class CacheManager implements Disposable { + void dispose() { + cache.clear(); + print('CacheManager disposed!'); + } +} + +final scope = CherryPick.openRootScope(); +scope.installModules([ + Module((bind) => bind().toProvide(() => CacheManager()).singleton()), +]); + +// ...later +await CherryPick.closeRootScope(); // prints: CacheManager disposed! +``` + +#### Async Example +```dart +class MyServiceWithSocket implements Disposable { + @override + Future dispose() async { + await socket.close(); + print('Socket closed!'); + } +} + +scope.installModules([ + Module((bind) => bind().toProvide(() => MyServiceWithSocket()).singleton()), +]); + +await CherryPick.closeRootScope(); // awaits async disposal +``` + +**Tip:** Always call `await CherryPick.closeRootScope()` or `await scope.closeSubScope(key)` in your shutdown/teardown logic to ensure all resources are released automatically. + +--- + ### Automatic resource management (`Disposable`, `dispose`) CherryPick automatically manages the lifecycle of any object registered via DI that implements the `Disposable` interface. @@ -318,6 +371,7 @@ scope.installModules([...]); - [x] Null-safe Resolution (tryResolve/tryResolveAsync) - [x] Circular Dependency Detection (Local and Global) - [x] Comprehensive logging of dependency injection state and actions +- [x] Automatic resource cleanup for all registered Disposable dependencies ## Quick Guide: Circular Dependency Detection