scheduleWarmUpFrame method Null safety

void scheduleWarmUpFrame()

Schedule a frame to run as soon as possible, rather than waiting for the engine to request a frame in response to a system "Vsync" signal.

This is used during application startup so that the first frame (which is likely to be quite expensive) gets a few extra milliseconds to run.

Locks events dispatching until the scheduled frame has completed.

If a frame has already been scheduled with scheduleFrame or scheduleForcedFrame, this call may delay that frame.

If any scheduled frame has already begun or if another scheduleWarmUpFrame was already called, this call will be ignored.

Prefer scheduleFrame to update the display in normal operation.

Implementation

void scheduleWarmUpFrame() {
  if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle) {
    return;
  }

  _warmUpFrame = true;
  final TimelineTask timelineTask = TimelineTask()..start('Warm-up frame');
  final bool hadScheduledFrame = _hasScheduledFrame;
  // We use timers here to ensure that microtasks flush in between.
  Timer.run(() {
    assert(_warmUpFrame);
    handleBeginFrame(null);
  });
  Timer.run(() {
    assert(_warmUpFrame);
    handleDrawFrame();
    // We call resetEpoch after this frame so that, in the hot reload case,
    // the very next frame pretends to have occurred immediately after this
    // warm-up frame. The warm-up frame's timestamp will typically be far in
    // the past (the time of the last real frame), so if we didn't reset the
    // epoch we would see a sudden jump from the old time in the warm-up frame
    // to the new time in the "real" frame. The biggest problem with this is
    // that implicit animations end up being triggered at the old time and
    // then skipping every frame and finishing in the new time.
    resetEpoch();
    _warmUpFrame = false;
    if (hadScheduledFrame) {
      scheduleFrame();
    }
  });

  // Lock events so touch events etc don't insert themselves until the
  // scheduled frame has finished.
  lockEvents(() async {
    await endOfFrame;
    timelineTask.finish();
  });
}