Introduction
Debugging is an essential part of Flutter development. GetX provides several tools and patterns to make debugging easier, from simple logging to tracking reactive state changes. This guide covers how to effectively log events, debug controllers, monitor navigation, and use DevTools with GetX. You'll learn techniques to catch issues early and build more reliable apps.
- Basic Logging with print and debugPrint
The simplest way to log is using print(). However, on large outputs, Flutter may truncate long strings. Use debugPrint() instead – it splits long strings into chunks, preventing truncation.
- GetX's Built‑in Logging
GetX provides a static Get.log() method that formats logs with a timestamp and a prefix. It's useful for distinguishing logs from different parts of the app.
- Logging Controller Lifecycle
Add logs in onInit, onReady, and onClose to verify that controllers are being created and disposed correctly.
- Debugging Reactive State Changes
Use workers to log when reactive variables change. This is invaluable for understanding why your UI updates (or doesn't).
- Debugging Navigation
To log every navigation, you can use Get.routeObserver or add a global middleware. A middleware can log route changes.
Alternatively, set a global routing callback in GetMaterialApp:
- Logging API Calls with Interceptors
If you use Dio, add a logging interceptor to log requests and responses. This is extremely helpful for debugging network issues.
- Using Flutter DevTools with GetX
Flutter DevTools provides a rich debugging experience. To inspect reactive state, you can use the 'Widget Inspector' to see widget rebuilds, and the 'Memory' tab to verify controllers are being disposed. Add breakpoints in onInit and onClose to trace lifecycle.
- Debugging Workers
If a worker isn't triggering, check that the reactive variable is actually changing. Add logs inside the worker callback and ensure the variable is updated. Also verify that the worker is registered after the variable is created (in onInit).
- Logging Errors Globally
Use the global error handling techniques covered in the getx-global-error-handler topic to log all uncaught exceptions. This helps catch issues that might otherwise go unnoticed.
- Performance Logging
To measure performance, use Stopwatch around critical operations. Log the duration to spot bottlenecks.
Best Practices
- Use
debugPrintinstead ofprint– Prevents truncation. - Log controller lifecycle – Helps ensure proper disposal.
- Use workers to track state changes – Great for debugging reactive flow.
- Add middleware for route logging – Track navigation easily.
- Use a logging interceptor for HTTP – See exactly what is sent/received.
- Keep logs informative but not noisy – Avoid flooding the console in production.
- Use conditional logging – Wrap logs with
kDebugModeto avoid logging in release builds. - Use DevTools – Leverage inspector and memory tools.
Common Mistakes
- ❌ Using
printfor long strings – May get truncated. ✅ UsedebugPrint. - ❌ Logging sensitive data – Tokens, passwords, etc. ✅ Redact or avoid logging sensitive info.
- ❌ Forgetting to add logs in workers – Hard to know if they fire. ✅ Add logs to see when workers run.
- ❌ Logging too much in production – Can impact performance and expose data.
✅ Use
kDebugModeor a configuration flag.
FAQ
- Q: How do I log only in debug mode?
A: Useif (kDebugMode) debugPrint(...).kDebugModeis a constant fromfoundation.dartthat is true in debug builds. - Q: Can I use
Get.logwith custom tags?
A:Get.logdoesn't support custom tags out of the box, but you can create your own wrapper. - Q: How to see which widgets are rebuilding?
A: Use DevTools' 'Widget Inspector' with 'Highlight repaints' enabled. This shows green borders around widgets that rebuild. - Q: Why is my worker not triggering?
A: Ensure the reactive variable is being updated (check with a log). Also ensure the worker is set up inonInit, not after the variable changes. - Q: How to log the entire state of a controller?
A: OverridetoStringin your controller and call it from a debug function, or usedebugPrint(controller.toString()).
Conclusion
Effective logging and debugging are essential for building reliable Flutter apps. GetX provides the building blocks to log state changes, lifecycle events, and navigation. By combining these with Flutter's DevTools and best practices, you can quickly identify and fix issues during development.