• Ian Hickson's avatar
    Flush microtasks after transient callbacks are run. (#9702) · e8c46927
    Ian Hickson authored
    This splits the frame pipeline into two, beginFrame and drawFrame.
    
    As part of making this change I added some debugging hooks that helped
    debug the issues that came up:
    
     * I added debugPrintScheduleFrameStacks which prints a stack whenever
       a frame is actually scheduled, so you can see why frames are being
       scheduled.
    
     * I added some toString output to EditableText and RawKeyboardListener.
    
     * I added a scheduler_tester.dart library for scheduler library tests.
    
     * I changed the test framework to flush microtasks before pumping.
    
     * Some asserts that had the old string literal form were replaced by
       asserts with messages.
    
    I also fixed a few subtle bugs that this uncovered:
    
     * setState() now calls `ensureVisualUpdate`, rather than
       `scheduleFrame`. This means that calling it from an
       AnimationController callback does not actually schedule an extra
       redundant frame as it used to.
    
     * I corrected some documentation.
    e8c46927
animation_test.dart 1.59 KB
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:test/test.dart';

import 'scheduler_tester.dart';

class TestSchedulerBinding extends BindingBase with SchedulerBinding { }

void main() {
  final SchedulerBinding scheduler = new TestSchedulerBinding();

  test("Check for a time dilation being in effect", () {
    expect(timeDilation, equals(1.0));
  });

  test("Can cancel queued callback", () {
    int secondId;

    bool firstCallbackRan = false;
    bool secondCallbackRan = false;

    void firstCallback(Duration timeStamp) {
      expect(firstCallbackRan, isFalse);
      expect(secondCallbackRan, isFalse);
      expect(timeStamp.inMilliseconds, equals(0));
      firstCallbackRan = true;
      scheduler.cancelFrameCallbackWithId(secondId);
    }

    void secondCallback(Duration timeStamp) {
      expect(firstCallbackRan, isTrue);
      expect(secondCallbackRan, isFalse);
      expect(timeStamp.inMilliseconds, equals(0));
      secondCallbackRan = true;
    }

    scheduler.scheduleFrameCallback(firstCallback);
    secondId = scheduler.scheduleFrameCallback(secondCallback);

    tick(const Duration(milliseconds: 16));

    expect(firstCallbackRan, isTrue);
    expect(secondCallbackRan, isFalse);

    firstCallbackRan = false;
    secondCallbackRan = false;

    tick(const Duration(milliseconds: 32));

    expect(firstCallbackRan, isFalse);
    expect(secondCallbackRan, isFalse);
  });
}