mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Always finish the timeline event logged by Element.inflateWidget (#101794)
This commit is contained in:
parent
fe6d09a9ef
commit
c62d103bb6
77
dev/tracing_tests/test/inflate_widget_update_test.dart
Normal file
77
dev/tracing_tests/test/inflate_widget_update_test.dart
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2014 The Flutter 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/scheduler.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'common.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
initTimelineTests();
|
||||||
|
test('Widgets with updated keys produce well formed timelines', () async {
|
||||||
|
await runFrame(() { runApp(const TestRoot()); });
|
||||||
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
|
|
||||||
|
debugProfileBuildsEnabled = true;
|
||||||
|
|
||||||
|
await runFrame(() {
|
||||||
|
TestRoot.state.updateKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
int buildCount = 0;
|
||||||
|
for (final TimelineEvent event in await fetchTimelineEvents()) {
|
||||||
|
if (event.json!['name'] == 'BUILD') {
|
||||||
|
final String ph = event.json!['ph'] as String;
|
||||||
|
if (ph == 'B') {
|
||||||
|
buildCount++;
|
||||||
|
} else if (ph == 'E') {
|
||||||
|
buildCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(buildCount, 0);
|
||||||
|
|
||||||
|
debugProfileBuildsEnabled = false;
|
||||||
|
}, skip: isBrowser); // [intended] uses dart:isolate and io.
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestRoot extends StatefulWidget {
|
||||||
|
const TestRoot({super.key});
|
||||||
|
|
||||||
|
static late TestRootState state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TestRoot> createState() => TestRootState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestRootState extends State<TestRoot> {
|
||||||
|
final Key _globalKey = GlobalKey();
|
||||||
|
Key _localKey = UniqueKey();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
TestRoot.state = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateKey() {
|
||||||
|
setState(() {
|
||||||
|
_localKey = UniqueKey();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
key: _localKey,
|
||||||
|
child: SizedBox(
|
||||||
|
key: _globalKey,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -3792,33 +3792,35 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Key? key = newWidget.key;
|
try {
|
||||||
if (key is GlobalKey) {
|
final Key? key = newWidget.key;
|
||||||
final Element? newChild = _retakeInactiveElement(key, newWidget);
|
if (key is GlobalKey) {
|
||||||
if (newChild != null) {
|
final Element? newChild = _retakeInactiveElement(key, newWidget);
|
||||||
assert(newChild._parent == null);
|
if (newChild != null) {
|
||||||
assert(() {
|
assert(newChild._parent == null);
|
||||||
_debugCheckForCycles(newChild);
|
assert(() {
|
||||||
return true;
|
_debugCheckForCycles(newChild);
|
||||||
}());
|
return true;
|
||||||
newChild._activateWithParent(this, newSlot);
|
}());
|
||||||
final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
|
newChild._activateWithParent(this, newSlot);
|
||||||
assert(newChild == updatedChild);
|
final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
|
||||||
return updatedChild!;
|
assert(newChild == updatedChild);
|
||||||
|
return updatedChild!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
final Element newChild = newWidget.createElement();
|
||||||
|
assert(() {
|
||||||
|
_debugCheckForCycles(newChild);
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
newChild.mount(this, newSlot);
|
||||||
|
assert(newChild._lifecycleState == _ElementLifecycle.active);
|
||||||
|
|
||||||
|
return newChild;
|
||||||
|
} finally {
|
||||||
|
if (isTimelineTracked)
|
||||||
|
Timeline.finishSync();
|
||||||
}
|
}
|
||||||
final Element newChild = newWidget.createElement();
|
|
||||||
assert(() {
|
|
||||||
_debugCheckForCycles(newChild);
|
|
||||||
return true;
|
|
||||||
}());
|
|
||||||
newChild.mount(this, newSlot);
|
|
||||||
assert(newChild._lifecycleState == _ElementLifecycle.active);
|
|
||||||
|
|
||||||
if (isTimelineTracked)
|
|
||||||
Timeline.finishSync();
|
|
||||||
|
|
||||||
return newChild;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _debugCheckForCycles(Element newChild) {
|
void _debugCheckForCycles(Element newChild) {
|
||||||
|
Loading…
Reference in New Issue
Block a user