flutter_safe_async 1.0.0
flutter_safe_async: ^1.0.0 copied to clipboard
Prevents setState called after dispose by safely managing async tasks in Flutter widgets.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_safe_async/flutter_safe_async.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: SafeAsyncExamplePage());
}
}
class SafeAsyncExamplePage extends StatefulWidget {
const SafeAsyncExamplePage({super.key});
@override
State<SafeAsyncExamplePage> createState() => _SafeAsyncExamplePageState();
}
class _SafeAsyncExamplePageState extends SafeState<SafeAsyncExamplePage> {
String _status = 'Waiting...';
int _counter = 0;
@override
void initState() {
super.initState();
/// ✅ SAFE FUTURE (API simulation)
SafeAsync.run(
isMounted: () => mountedSafe,
task: () async {
await Future.delayed(const Duration(seconds: 3));
safeSetState(() {
_status = 'API Loaded Successfully';
});
},
onError: (e) {
debugPrint('Error: $e');
},
);
/// ✅ SAFE TIMER (auto cancelled on dispose)
final timer = Timer.periodic(const Duration(seconds: 1), (_) {
safeSetState(() {
_counter++;
});
});
registerTimer(timer);
/// ✅ SAFE STREAM (auto cancelled on dispose)
final stream = Stream.periodic(const Duration(seconds: 2), (count) => count)
.listen((event) {
safeSetState(() {
_status = 'Stream event: $event';
});
});
registerSubscription(stream);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('flutter_safe_async Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_status, style: const TextStyle(fontSize: 18)),
const SizedBox(height: 20),
Text('Counter: $_counter', style: const TextStyle(fontSize: 24)),
const SizedBox(height: 40),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Leave Page (No Crash)'),
),
],
),
),
);
}
}