Optimization & Debugging
Performance in Dart goes beyond UI rendering; it’s about efficient execution, smart resource utilization, and sound error handling.
Dart Performance Patterns
- Standardize Types: Avoid
dynamic. Use explicit types orObject?. Statically typed code allows the compiler to perform far better optimizations. - Efficient Collections:
- Use
Setfor average O(1) containment checks. - Use
Listfor ordered indexing. - Prefer
Iterablemethods (map,where) for readability, but useforloops in performance-critical hot paths.
- Use
- Inlining: Small getters and trivial functions are often inlined by the VM/AOT, but keeping them simple ensures this optimization happens.
Compile-Time Optimizations
- Final & Const: Declare variables as
finalwhenever possible. Useconstconstructors for widgets and data models to enable compile-time allocation and reduce runtime garbage collection pressure. - Ternary vs If-Else: In Dart, they are generally equivalent, but prioritize readability. Use
switchexpressions (Dart 3+) for exhaustive and efficient pattern matching. - Extension Types: Use Dart 3.3+
extension typezero-cost abstractions for type wrapping to eliminate runtime allocation overhead (see [dart-modern-syntax](file:///Users/dhruvanbhalara/Desktop/Github%20Projects/skills/skills/dart/dart-modern-syntax/SKILL.md)). - Private Named Parameters: Use Dart 3.12+
MyClass({this._privateField})constructors to eliminate initializer list code boilerplate (see [dart-modern-syntax](file:///Users/dhruvanbhalara/Desktop/Github%20Projects/skills/skills/dart/dart-modern-syntax/SKILL.md)).
Hot Paths & Loops
- Minimize Work in Loops: Extract calculations and object creations outside of loops.
- Collection Literals: Use literal syntax
[]or{}instead of constructors likeList()for brevity and minor performance gains.
Type System & Soundness
Enforce Dart’s sound type system to prevent runtime invalid states.
- Method Overrides: Maintain sound return types (covariant) and parameter types (contravariant). Never tighten a parameter type in a subclass unless explicitly marked with the
covariantkeyword. - Generics & Collections: Add explicit type annotations to generic classes (e.g.,
List<T>). Never assign aList<dynamic>to a typed list. - Downcasting: Avoid implicit downcasts from
dynamic. Use explicit casts (e.g.,as List<Cat>) when necessary, but ensure the underlying runtime type matches to preventTypeErrorexceptions. - Strict Casts: Enable
strict-casts: trueinanalysis_options.yamlto force explicit casting and catch implicit downcast errors at compile time.
Null Safety & Error Handling
Eliminate static errors related to null safety by correctly managing variable initialization and nullability.
- Modifiers: Apply
?for nullable types,!for null assertions, andrequiredfor named parameters that cannot be null. - Late Initialization: Use the
latekeyword for non-nullable variables guaranteed to be initialized before use. - Catching: Catch
Exceptionsubtypes for recoverable failures. - Errors: Never explicitly catch
Erroror its subtypes (e.g.,TypeError,ArgumentError). Errors indicate programming bugs that must be fixed, not caught. - Rethrowing: Use
rethrowinside acatchblock to propagate an exception while preserving its original stack trace.
Profiling & Debugging
- DevTools CPU Profiler: Identify hot paths and “heavy” functions.
- Benchmarking: Use
package:benchmark_harnessfor scientific performance measurement of non-UI logic. - Hot Reload vs Restart: Use hot reload for UI changes. For state initialization or deep logic changes that cause runtime errors, use hot restart to clear the state tree.