A collection of hands-on experiments exploring Flutter and Dart runtime behavior, performance characteristics, and common pitfalls. Each lab is a self-contained experiment with detailed documentation and code demonstrating critical concepts for production Flutter development.
This project serves as a practical reference for understanding:
- Dart event loop mechanics and asynchronous execution
- Isolate-based concurrency patterns
- Flutter frame rendering pipeline and performance budgets
- Memory leak detection and prevention
- Efficient data transfer between isolates
Type: CLI Dart application
Concepts: Event loop priority, microtask vs event queue, async/await continuation scheduling
Demonstrates how Dart's event loop processes synchronous code, microtasks, and events. Shows how microtask flooding can starve the event queue and why async/await doesn't provide CPU concurrency.
dart labs/01_event_loop/bin/main.dartKey Takeaways:
- Execution order: Sync → Microtask Queue → Event Queue
- Microtask starvation can block UI rendering in Flutter
async/awaitis for I/O concurrency, not CPU parallelism
Type: CLI Dart application
Concepts: Isolate spawning, main thread blocking, CPU-bound work distribution
Compares the impact of running heavy CPU work on the main isolate versus offloading it to a spawned isolate. Proves that isolates prevent main thread blocking.
dart labs/02_cpu_isolates/bin/main.dartKey Takeaways:
- CPU work on main isolate blocks everything (timers, events, UI)
- Spawning isolates keeps the main thread responsive
- Use isolates (or Flutter's
compute()) for heavy computation
Type: Flutter UI application
Concepts: 16ms frame budget, build/layout/paint phases, jank detection
Interactive experiment showing how expensive operations in build, layout, and paint phases exceed the 16ms frame budget, causing dropped frames and UI jank.
flutter run --profileKey Takeaways:
- Each phase (build/layout/paint) contributes to frame time
- Intrinsic measurements and heavy paint effects are expensive
- Profile with DevTools timeline to identify bottlenecks
Type: Flutter UI application
Concepts: Controller disposal, subscription lifecycle, singleton retention, memory profiling
Demonstrates 3 common memory leak patterns in Flutter with reproducible proof via DevTools memory snapshots.
flutter run --profileLeaks Demonstrated:
- Not disposing controllers (
TextEditingController, etc.) - Stream subscriptions never canceled
- Singletons retaining widget references
Key Takeaways:
- Always dispose controllers in
dispose() - Cancel stream subscriptions to prevent leaks
- Be careful with singletons—they prevent garbage collection
Type: CLI Dart application
Concepts: Zero-copy data transfer, isolate communication optimization, serialization overhead
Benchmarks data transfer between isolates, comparing regular Uint8List (serialized/copied) versus TransferableTypedData (transferred without copying).
dart labs/05_transferable_data/bin/main.dartKey Takeaways:
TransferableTypedDatais dramatically faster for large payloads- Regular typed data gets serialized/copied when sent to isolates
- Use
.fromList()+.materialize()for efficient transfers
flutter_lab/
├── README.md # This file
├── pubspec.yaml # Flutter project dependencies
├── labs/ # Lab experiments
│ ├── 01_event_loop/
│ │ ├── README.md # Lab documentation
│ │ └── bin/main.dart # CLI executable
│ ├── 02_cpu_isolates/
│ │ ├── README.md
│ │ └── bin/main.dart
│ ├── 03_frame_budget/
│ │ ├── README.md
│ │ └── lib/main.dart # Flutter UI app
│ ├── 04_memory_leaks/
│ │ ├── README.md
│ │ └── lib/main.dart # Flutter UI app
│ └── 05_transferable_data/
│ ├── README.md
│ └── bin/main.dart # CLI executable
└── tools/
└── scripts/ # Utility scripts (future)
- Flutter SDK (3.0+)
- Dart SDK (3.0+)
- IDE with Flutter/Dart support (VS Code, Android Studio, IntelliJ)
git clone https://github.com/dan-oliveiraa/flutter_lab.git
cd flutter_lab
flutter pub getCLI Labs (01, 02, 05):
dart labs/<lab_name>/bin/main.dartFlutter UI Labs (03, 04):
flutter run --profile
# Note: You'll need to copy the lab's lib/main.dart to the root lib/main.dart
# Or set up each lab as a standalone Flutter projectUse Flutter DevTools for memory profiling and timeline analysis:
flutter run --profile
flutter pub global activate devtools
flutter pub global run devtoolsFor Memory Leaks (LAB 04):
- Take baseline snapshot
- Run 30-60 push/pop cycles
- Force garbage collection
- Take second snapshot
- Compare retained instances
For Frame Budget (LAB 03):
- Enable Timeline in DevTools
- Toggle pressure modes
- Observe frame rendering times in timeline
- Identify which phase exceeds 16ms budget
Recommended Order:
- LAB 01 - Understand event loop fundamentals
- LAB 02 - Learn when to use isolates
- LAB 05 - Optimize isolate communication
- LAB 03 - Master Flutter rendering pipeline
- LAB 04 - Prevent memory leaks in production
This is a learning project. Feel free to:
- Add new experiments
- Improve documentation
- Report issues or suggest improvements
This project is open source and available for educational purposes.
Built with ❤️ for the Flutter community