free_disposer 1.1.3
free_disposer: ^1.1.3 copied to clipboard
A Dart resource management library using Finalizer to automatically dispose resources when objects are garbage collected.
example/free_disposer_example.dart
import 'dart:async';
import 'dart:io';
import 'package:free_disposer/free_disposer.dart';
void main() async {
print('Free Disposer Examples\n');
await basicUsageExample();
await autoCleanupExample();
await manualCleanupExample();
await complexScenarioExample();
await customAdapterExample();
print('\nAll examples completed!');
}
/// Basic usage with DisposableMixin
Future<void> basicUsageExample() async {
print('Example 1: Basic Usage - DisposableMixin');
final service = MyService();
final timer = Timer.periodic(
Duration(seconds: 1),
(_) => print(' Timer tick'),
);
final controller = StreamController<String>();
controller.stream.listen((data) => print(' Received: $data'));
// Attach resources to service
timer.disposeBy(service);
controller.disposeBy(service);
controller.add('Hello');
controller.add('World');
await Future.delayed(Duration(seconds: 2));
// Dispose all resources
await service.dispose();
print(' Resources disposed\n');
}
/// Auto cleanup when object is GC'd
Future<void> autoCleanupExample() async {
print('Example 2: Auto Cleanup - GC Finalizer');
var finalizerExecuted = false;
void createAutoCleanupObject() {
final object = Object();
final timer = Timer.periodic(
Duration(milliseconds: 500),
(_) => print(' Auto timer tick'),
);
object.disposeWith(() {
timer.cancel();
finalizerExecuted = true;
print(' Finalizer executed: Timer auto-cleaned!');
});
}
createAutoCleanupObject();
await Future.delayed(Duration(seconds: 2));
// Force GC
await _forceGC();
await Future.delayed(Duration(milliseconds: 500));
if (finalizerExecuted) {
print(' Auto cleanup successful!');
} else {
print(' Finalizer may not have executed yet (normal)');
}
print('');
}
/// Manual cleanup using AutoDisposer
Future<void> manualCleanupExample() async {
print('Example 3: Manual Cleanup - AutoDisposer');
final object = Object();
final httpClient = HttpClient();
final timer = Timer.periodic(
Duration(seconds: 1),
(_) => print(' HTTP timer tick'),
);
// Attach disposers
object.disposeWith(() {
httpClient.close();
print(' HTTP Client closed');
});
object.disposeWith(() {
timer.cancel();
print(' Timer cancelled');
});
print(' Attached ${object.attachedDisposerCount} disposers');
await Future.delayed(Duration(seconds: 2));
// Manual dispose
await object.disposeAttached();
print(' Manual cleanup completed\n');
}
/// Complex scenario with multiple resource layers
Future<void> complexScenarioExample() async {
print('Example 4: Complex Scenario - Multi-layer Resources');
final app = MyApp();
await app.start();
await Future.delayed(Duration(seconds: 3));
await app.stop();
print(' Complex scenario completed\n');
}
class MyService with DisposableMixin {
MyService() {
print(' MyService created');
}
@override
Future<void> dispose() async {
print(' MyService disposing...');
await super.dispose();
print(' MyService disposed');
}
}
class MyApp with DisposableMixin {
late StreamController<String> _messageController;
late Timer _heartbeatTimer;
late HttpClient _httpClient;
late StreamSubscription _messageSubscription;
Future<void> start() async {
print(' Starting app...');
_messageController = StreamController<String>();
_messageController.disposeBy(this);
_heartbeatTimer = Timer.periodic(Duration(seconds: 1), (_) {
_messageController.add('heartbeat');
});
_heartbeatTimer.disposeBy(this);
_httpClient = HttpClient();
_httpClient.disposeBy(this);
_messageSubscription = _messageController.stream.listen((message) {
print(' $message');
});
_messageSubscription.disposeBy(this);
disposeWith(() => print(' Custom cleanup executed'));
print(' App started');
}
Future<void> stop() async {
await dispose();
}
@override
Future<void> dispose() async {
print(' MyApp disposing...');
await super.dispose();
print(' MyApp disposed');
}
}
/// Force GC for demonstration
Future<void> _forceGC() async {
for (int i = 0; i < 1000; i++) {
final temp = List.generate(1000, (index) => i * index);
temp.clear();
}
await Future.delayed(Duration(milliseconds: 100));
for (int i = 0; i < 500; i++) {
final temp = List.generate(2000, (index) => i * index);
temp.clear();
}
await Future.delayed(Duration(milliseconds: 200));
}
/// Custom adapter example for third-party types
Future<void> customAdapterExample() async {
print('Example 5: Custom Adapters - Third-party Types');
// Register custom adapter
DisposerAdapterManager.register<DatabaseConnection>(
(db) => db.close,
);
print(' Registered custom adapter');
// Create service and custom resource
final service = MyService();
final db = DatabaseConnection('user_db');
// Now works with disposeWith thanks to adapter
db.disposeBy(service);
print(' Database attached to service');
// Use resource
db.query('SELECT * FROM users');
await Future.delayed(Duration(seconds: 1));
// Dispose all resources (including custom one)
await service.dispose();
// Clean up adapter
DisposerAdapterManager.clear();
print(' Custom adapter example completed\n');
}
// Custom classes for demonstration
class DatabaseConnection {
final String name;
bool _isConnected = true;
DatabaseConnection(this.name) {
print(' Database connected: $name');
}
void query(String sql) {
if (_isConnected) {
print(' Executing query: $sql');
}
}
void close() {
if (_isConnected) {
_isConnected = false;
print(' Database connection closed: $name');
}
}
}