run<T> static method

Future<T> run<T>(
  1. Future<T> work(), {
  2. String? label,
})

Runs work in the root zone and announces it, the way track does.

The root zone is not a detail. A harness runs each screen in a zone of its own, and a future a dependency memoizes — an engine's one-time initialisation, an importer's shared tables — belongs to the zone that first created it. An await on that future from a later screen's zone never resumes: the continuation is queued to a zone whose queue nobody drains any more. Measured 2026-09-05: the first mount of a 3D probe loaded in two seconds, every mount after it waited out the whole ceiling with the load still pending. Run from the root zone, the continuations of work live on the real event loop, which every zone shares, and the caller's own await on the returned future resumes in the caller's zone as it should.

This is the entry point for loading anything a dependency caches: await RealWork.run(() => loadModel(bundle), label: 'model').

Lottie is the common one. With backgroundLoading: true it reads the file through the bundle, which a scenario counts, and then parses it with compute, which nothing counts — and it keeps every load for the life of the process, which is what makes this run rather than track. Start the load here and hand the builder the same provider, so it finds the announced load rather than starting one of its own:

final _intro = AssetLottie('assets/intro.json', backgroundLoading: true);

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  RealWork.run(() => _intro.load(context: context), label: 'intro');
}

@override
Widget build(BuildContext context) => LottieBuilder(lottie: _intro);

Its outcome — value or error — is handed back through a future that belongs to the caller's zone, so an error is the caller's to catch and never the root zone's to report as unhandled, which under a test binding ends the process.

Implementation

static Future<T> run<T>(Future<T> Function() work, {String? label}) {
  var done = Completer<T>();
  Zone.root.run(() {
    work().then(done.complete, onError: done.completeError);
  });
  return track(done.future, label: label);
}