Lambdas

onComplete

Bottom line: onAnimationEnd: widget.onComplete is the preferred and most efficient when the API accepts VoidCallback?.

Using a lambda

() => widget.onComplete?.call()
  • Behavior:

    • creates a new closure that, when run, checks and invokes onComplete if non-null.
    • widget.onComplete just passes the function reference (or null) through.
  • Allocation:

    • The lambda form allocates a new closure every build.
    • Passing widget.onComplete does not allocate anything new.
  • Null semantics:

  • With the lambda, onAnimationEnd is always non-null (a no-op if onComplete is null).

  • Passing widget.onComplete preserves null vs non-null, which some widgets use to change behavior/optimizations.

Recommendation

  • Prefer: onAnimationEnd: widget.onComplete when the parameter type is VoidCallback?.
  • It’s simpler, avoids an extra allocation, preserves intended semantics, and satisfies the Dart lint “unnecessary_lambdas”.
  • Use a wrapper only if you need extra logic (e.g., chaining, arguments, logging):
onAnimationEnd: () { widget.onComplete?.call(); doSomethingElse(); }

If the target parameter is non-nullable

  • If onAnimationEnd is VoidCallback (non-nullable) but onComplete is nullable, use a no-op fallback:
  • onAnimationEnd: widget.onComplete ?? _noop
  • Define _noop once to avoid per-build allocations: void _noop() {} (top-level or static void _noop() {}).
  • Avoid () => widget.onComplete?.call() in this case unless you need the extra logic; it allocates a closure every build.