docs+feat: add Disposable interface source and usage example

feat(core,doc): unified async dispose mechanism for resource cleanup

BREAKING CHANGE:

- Added full support for asynchronous resource cleanup via a unified FutureOr<void> dispose() method in the Disposable interface.
- The Scope now provides only Future<void> dispose() for disposing all tracked resources and child scopes (sync-only dispose() was removed).
- All calls to cleanup in code and tests (scope itself, subscopes, and custom modules) now require await ...dispose().
- Documentation and all examples updated: resource management is always async and must be awaited; Disposable implementers may use both sync and async cleanup.
- Old-style, synchronous cleanup methods have been completely removed (API is now consistently async for all DI lifecycle management).
- Example and tutorial code now demonstrate async resource disposal patterns.
This commit is contained in:
Sergey Penkovsky
2025-08-01 15:07:12 +03:00
parent 61f2268d63
commit a9c95f6a89
14 changed files with 516 additions and 69 deletions

View File

@@ -185,6 +185,41 @@ final service = scope.tryResolve<OptionalService>(); // вернет null, ес
---
## Автоматическое управление ресурсами: Disposable и dispose
CherryPick позволяет автоматически очищать ресурсы для ваших синглтонов и любых сервисов, зарегистрированных через DI.
Если ваш класс реализует интерфейс `Disposable`, всегда вызывайте и **await**-те `scope.dispose()` (или `CherryPick.closeRootScope()`), когда хотите освободить все ресурсы — CherryPick дождётся завершения `dispose()` для всех объектов, которые реализуют Disposable и были резолвлены из DI.
Это позволяет избежать утечек памяти, корректно завершать процессы и грамотно освобождать любые ресурсы (файлы, потоки, соединения и т.д., включая async).
### Пример
```dart
class LoggingService implements Disposable {
@override
FutureOr<void> dispose() async {
// Закрыть файлы, потоки, соединения и т.д. (можно с await)
print('LoggingService disposed!');
}
}
Future<void> main() async {
final scope = openRootScope();
scope.installModules([
_LoggingModule(),
]);
final logger = scope.resolve<LoggingService>();
// Используем logger...
await scope.dispose(); // выведет: LoggingService disposed!
}
class _LoggingModule extends Module {
@override
void builder(Scope scope) {
bind<LoggingService>().toProvide(() => LoggingService()).singleton();
}
}
```
## Внедрение зависимостей через аннотации и автогенерацию
CherryPick поддерживает DI через аннотации, что позволяет полностью избавиться от ручного внедрения зависимостей.