mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

Provide a way to schedule a callback for immediately after the current frame has been sent to the GPU thread. This is useful for times where you want to immediately schedule yourself for another build or layout because, for instance, you just displayed frame zero of an animation and you want to use the metrics from that layout to set up the actual animation to begin immediately, such that the very next frame is frame 1.
134 lines
3.5 KiB
Dart
134 lines
3.5 KiB
Dart
import 'package:flutter/animation.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'widget_tester.dart';
|
|
import 'test_widgets.dart';
|
|
|
|
class ProbeWidget extends StatefulComponent {
|
|
ProbeWidgetState createState() => new ProbeWidgetState();
|
|
}
|
|
|
|
class ProbeWidgetState extends State<ProbeWidget> {
|
|
static int buildCount = 0;
|
|
|
|
void initState() {
|
|
super.initState();
|
|
setState(() {});
|
|
}
|
|
|
|
void didUpdateConfig(ProbeWidget oldConfig) {
|
|
setState(() {});
|
|
}
|
|
|
|
Widget build(BuildContext context) {
|
|
setState(() {});
|
|
buildCount++;
|
|
return new Container();
|
|
}
|
|
}
|
|
|
|
class BadWidget extends StatelessComponent {
|
|
BadWidget(this.parentState);
|
|
|
|
final State parentState;
|
|
|
|
Widget build(BuildContext context) {
|
|
parentState.setState(() {});
|
|
return new Container();
|
|
}
|
|
}
|
|
|
|
class BadWidgetParent extends StatefulComponent {
|
|
BadWidgetParentState createState() => new BadWidgetParentState();
|
|
}
|
|
|
|
class BadWidgetParentState extends State<BadWidgetParent> {
|
|
Widget build(BuildContext context) {
|
|
return new BadWidget(this);
|
|
}
|
|
}
|
|
|
|
class BadDisposeWidget extends StatefulComponent {
|
|
BadDisposeWidgetState createState() => new BadDisposeWidgetState();
|
|
}
|
|
|
|
class BadDisposeWidgetState extends State<BadDisposeWidget> {
|
|
Widget build(BuildContext context) {
|
|
return new Container();
|
|
}
|
|
|
|
void dispose() {
|
|
setState(() {});
|
|
super.dispose();
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
dynamic cachedException;
|
|
|
|
// ** WARNING **
|
|
// THIS TEST OVERRIDES THE NORMAL EXCEPTION HANDLING
|
|
// AND DOES NOT REPORT EXCEPTIONS FROM THE FRAMEWORK
|
|
|
|
setUp(() {
|
|
assert(cachedException == null);
|
|
debugWidgetsExceptionHandler = (String context, dynamic exception, StackTrace stack) {
|
|
cachedException = exception;
|
|
};
|
|
debugSchedulerExceptionHandler = (dynamic exception, StackTrace stack) { throw exception; };
|
|
});
|
|
|
|
tearDown(() {
|
|
assert(cachedException == null);
|
|
cachedException = null;
|
|
debugWidgetsExceptionHandler = null;
|
|
debugSchedulerExceptionHandler = null;
|
|
});
|
|
|
|
test('Legal times for setState', () {
|
|
testWidgets((WidgetTester tester) {
|
|
GlobalKey flipKey = new GlobalKey();
|
|
expect(ProbeWidgetState.buildCount, equals(0));
|
|
tester.pumpWidget(new ProbeWidget());
|
|
expect(ProbeWidgetState.buildCount, equals(1));
|
|
tester.pumpWidget(new ProbeWidget());
|
|
expect(ProbeWidgetState.buildCount, equals(2));
|
|
tester.pumpWidget(new FlipComponent(
|
|
key: flipKey,
|
|
left: new Container(),
|
|
right: new ProbeWidget()
|
|
));
|
|
expect(ProbeWidgetState.buildCount, equals(2));
|
|
(flipKey.currentState as FlipComponentState).flip();
|
|
tester.pump();
|
|
expect(ProbeWidgetState.buildCount, equals(3));
|
|
(flipKey.currentState as FlipComponentState).flip();
|
|
tester.pump();
|
|
expect(ProbeWidgetState.buildCount, equals(3));
|
|
tester.pumpWidget(new Container());
|
|
expect(ProbeWidgetState.buildCount, equals(3));
|
|
});
|
|
});
|
|
|
|
test('Setting parent state during build is forbidden', () {
|
|
testWidgets((WidgetTester tester) {
|
|
expect(cachedException, isNull);
|
|
tester.pumpWidget(new BadWidgetParent());
|
|
expect(cachedException, isNotNull);
|
|
cachedException = null;
|
|
tester.pumpWidget(new Container());
|
|
expect(cachedException, isNull);
|
|
});
|
|
});
|
|
|
|
test('Setting state during dispose is forbidden', () {
|
|
testWidgets((WidgetTester tester) {
|
|
tester.pumpWidget(new BadDisposeWidget());
|
|
expect(() {
|
|
tester.pumpWidget(new Container());
|
|
}, throws);
|
|
});
|
|
});
|
|
}
|