subscription-holder-lifecycle
Use when managing and automatically cancelling multiple Dart StreamSubscriptions in Flutter State, ChangeNotifier, or StateNotifier classes using subscription_holder.
来源信息
- 仓库
- mono0926/flutter_mono_kit
- 最近来源活动
- 2026年9月9日 03:07
- 检测到的 SKILL.md 语言
- 英语
- 星标
- 66
- 分支
- 4
安装方式
默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。
检查来源文件
决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。
正在显示 SKILL.md
SKILL.md
来源说明 · 只读预览- name
- subscription_holder-lifecycle
- description
- Use when managing and automatically cancelling multiple Dart StreamSubscriptions in Flutter State, ChangeNotifier, or StateNotifier classes using subscription_holder.
# subscription_holder Lifecycle Management Guide
`subscription_holder` eliminates manual tracking and disposal of multiple `StreamSubscription` instances. It acts as a disposable container (similar to Rx CompositeDisposable) that cancels all active subscriptions cleanly when tearing down state.
## Guidelines
- **Using `SubscriptionHolder`**:
- Instantiate `final _subscriptions = SubscriptionHolder();`.
- Add active subscriptions via `_subscriptions.add(stream.listen(...))` or use the fluent extension `.addTo(_subscriptions)`.
- Call `_subscriptions.dispose()` inside `State.dispose()`, `ChangeNotifier.dispose()`, or controller teardown.
- **Using `SubscriptionHolderMixin`**:
- Mix in `SubscriptionHolderMixin` directly onto state classes or controller classes to access `addSubscription(stream.listen(...))` and automatic disposal.
- **Auto-Cancellation**:
- `dispose()` cancels all registered subscriptions and prevents subsequent additions.
- To cancel existing subscriptions without invalidating the container (e.g., when resetting state), call `_subscriptions.cancelAll()`.
## Examples
### 1. Managing Subscriptions in a StatefulWidget
```dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:subscription_holder/subscription_holder.dart';
class EventMonitorWidget extends StatefulWidget {
const EventMonitorWidget({super.key, required this.eventStream, required this.errorStream});
final Stream<String> eventStream;
final Stream<dynamic> errorStream;
@override
State<EventMonitorWidget> createState() => _EventMonitorWidgetState();
}
class _EventMonitorWidgetState extends State<EventMonitorWidget> {
final _subscriptions = SubscriptionHolder();
@override
void initState() {
super.initState();
// Using .addTo() extension
widget.eventStream.listen((event) {
debugPrint('Received: $event');
}).addTo(_subscriptions);
// Using .add() directly
_subscriptions.add(widget.errorStream.listen((err) {
debugPrint('Error: $err');
}));
}
@override
void dispose() {
_subscriptions.dispose(); // Cancels both subscriptions immediately
super.dispose();
}
@override
Widget build(BuildContext context) {
return const SizedBox.shrink();
}
}
```
### 2. Using `SubscriptionHolderMixin` in StateNotifier / ChangeNotifier
```dart
import 'package:flutter/foundation.dart';
import 'package:subscription_holder/subscription_holder.dart';
class SessionController extends ChangeNotifier with SubscriptionHolderMixin {
SessionController(Stream<bool> authStateStream, Stream<int> tickStream) {
authStateStream.listen((isAuthenticated) {
// Handle auth update
notifyListeners();
}).addTo(subscriptionHolder);
tickStream.listen((tick) {
// Handle timer tick
}).addTo(subscriptionHolder);
}
@override
void dispose() {
disposeSubscriptions();
super.dispose();
}
}
```
## Common Pitfalls & Anti-Patterns
- ❌ **Anti-pattern**: Manually maintaining individual nullable `StreamSubscription? _sub1; StreamSubscription? _sub2;` variables and cancelling each in `dispose()`, which is error-prone and easily leads to memory leaks.
- ✔️ **Correct**: Collect all subscriptions into `SubscriptionHolder` and dispose them together.
- ❌ **Anti-pattern**: Calling `add()` on a `SubscriptionHolder` that has already been disposed.
- ✔️ **Correct**: Only register subscriptions during the active lifecycle of the component.
在 GitHub 查看