auto_dispose_mixin 1.1.0
auto_dispose_mixin: ^1.1.0 copied to clipboard
A lightweight Flutter mixin that automatically disposes controllers, subscriptions, and other resources to prevent memory leaks.
Auto Dispose Mixin #
Zero-Boilerplate Lifecycle Management for Flutter Widgets
auto_dispose_mixin automatically disposes controllers, subscriptions, notifiers, and custom resources when a StatefulWidget is removed from the widget tree β without overriding dispose().
Designed for performance, safety, and developer ergonomics.
π Why This Package Exists #
Memory leaks are one of the most common performance issues in Flutter apps.
Typical problems:
- Forgetting to dispose
TextEditingController - Leaking
StreamSubscription - Missing
AnimationController.dispose() - Bloated
dispose()methods - Inconsistent cleanup across teams
β Traditional Approach #
@override
void dispose() {
controller.dispose();
scrollController.dispose();
animationController.dispose();
subscription.cancel();
super.dispose();
}
β With AutoDisposeMixin #
class _MyWidgetState extends State<MyWidget>
with AutoDisposeMixin {
late final controller =
registerForDispose(TextEditingController());
// No dispose() override needed π
}
β¨ Features #
- β Automatic disposal of common Flutter resources
- β Works with AnimationController (ticker-safe)
- β Stream subscription cleanup
- β Custom disposable objects
- β
Duck typing (
dispose()detection) - β Manual cleanup callbacks
- β DevTools logging
- β Performance timing
- β Zero runtime overhead in release mode
- β No code generation
- β No reflection
- β No magic
π¦ Installation #
Add to pubspec.yaml:
dependencies:
auto_dispose_mixin: ^1.*.*
Then run:
flutter pub get
π§© Basic Usage #
Step 1: Add the mixin #
class _MyPageState extends State<MyPage>
with AutoDisposeMixin {
Step 2: Register disposables #
late final TextEditingController controller =
registerForDispose(TextEditingController());
late final ScrollController scrollController =
registerForDispose(ScrollController());
Thatβs it.
No dispose() override required.
π― Supported Disposable Types #
AutoDisposeMixin automatically handles an exhaustive list of Flutter and Dart controllers, natively saving you from writing disposal boilerplate.
ChangeNotifier / ValueNotifier Family #
(Most UI Controllers)
TextEditingControllerScrollController,PageController,TabControllerAnimationControllerFocusNode,FocusScopeNodeSearchController- Any custom class extending
ChangeNotifierorValueNotifier
Streams & Sinks #
(Async Data)
StreamSubscriptionβ.cancel()StreamController,BroadcastStreamControllerβ.close()IOSink,EventSink,WebSocketβ.close()
UI & Flutter Core #
OverlayEntryβ Natively calls.remove()if mounted, then.dispose()Timer/RestartableTimerβ.cancel()Tickerβ.stop(),.dispose()
Custom Disposable Interface #
abstract class Disposable {
bool get isDisposed;
void dispose();
void markDisposed();
}
Advanced Duck Typing (The "Senior Dev" Checklist) #
If your object isn't in the standard Flutter list above, AutoDisposeMixin will dynamically detect and safely call its cleanup method. This automatically handles thousands of 3rd party plugins (like VideoPlayerController, GetX Worker, etc).
The mixin implicitly supports anything that has:
.dispose()(e.g.TapGestureRecognizer, Plugin controllers).cancel()(e.g.Worker,EventChannelsubscriptions).close()(e.g.ReceivePort,PersistentBottomSheetController).kill()(e.g.Isolate)
class FakeSocketClient {
void close() {
print('Socket closed');
}
}
late final socket =
registerForDispose(FakeSocketClient());
Manual Cleanup #
registerDisposeCallback(() {
// custom cleanup
});
π AnimationController & Ticker Support #
β Correct Mixin Order (IMPORTANT) #
When using tickers:
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin, AutoDisposeMixin {
Rule:
AutoDisposeMixinmust be the last mixin.
Why? #
- Flutter requires ticker providers to be initialized first
- AutoDisposeMixin depends on fully constructed controllers
π§ Example: AnimationController #
late final AnimationController animationController =
registerForDispose(
AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
),
);
The package will:
- Stop animation if running
- Dispose safely
- Track performance (optional)
π StreamSubscription Example #
late final StreamSubscription<int> subscription =
registerForDispose(
Stream.periodic(const Duration(seconds: 1))
.listen(print),
);
Automatically calls .cancel() on dispose.
π§ͺ Custom Disposable Example #
class FakeSocketClient {
void dispose() {
print('Socket closed');
}
}
late final socket =
registerForDispose(FakeSocketClient());
Duck typing detects .dispose() automatically.
π§Ή Manual Dispose Callback #
For edge cases:
registerDisposeCallback(() {
debugPrint('Manual cleanup');
});
Executed after all registered disposables.
π Debug & DevTools Integration #
Enable Debug Reporting #
void main() {
AutoDisposeDebug.debugReportEnabled = true;
AutoDisposeDebug.trackPerformance = true;
runApp(MyApp());
}
What You Get #
- β Per-object dispose logs
- β Non-disposable warnings
- β Total dispose time
- β DevTools timeline visibility
Example output:
Dispose Summary for _MyPageState
---------------------------------
Disposed: 6
Not Disposable: 1
Total Time: 312Β΅s
π Performance Tracking #
When enabled:
- Each disposable tracks execution time
- Total dispose duration is logged
- Uses
Stopwatchinternally - Disabled in release mode by default
β οΈ Best Practices #
β DO #
- Use
late finalwithregisterForDispose - Keep AutoDisposeMixin last
- Enable debug mode during development
β DONβT #
- Manually call
.dispose()on registered objects - Register objects after
dispose()is called - Use with non-State classes
π§ͺ Example App #
To generate an example project:
flutter create example
Then import your package:
import 'package:auto_dispose_mixin/auto_dispose_mixin.dart';
A full example is included in /example.
π§© Architecture Philosophy #
- No code generation
- No build_runner
- No reflection
- No runtime cost
- Flutter-native lifecycle
- Predictable behavior
This package augments Flutter β it does not fight it.
π£ Roadmap #
Planned features:
- Leak detection warnings
- DevTools UI extension
- Dispose order visualization
- Zone-based lifecycle scopes
β€οΈ Contributing #
Contributions welcome.
- Add new disposable resolvers
- Improve DevTools logging
- Write tests
- Improve documentation
π License #
MIT License
https://github.com/ASHISH1317/auto_dispose_mixin/blob/main/LICENSE
β Final Note #
If youβve ever forgotten to dispose something in Flutter this package is for you.
Simple. Safe. Fast.