Allow current leader of layerlink to detach before the previous leade… (#96810)

This commit is contained in:
chunhtai 2022-01-24 11:50:11 -08:00 committed by GitHub
parent 62e745612a
commit 28ca7bd789
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 6 deletions

View file

@ -2118,8 +2118,8 @@ class LayerLink {
assert((){
if (_leader != null) {
_debugPreviousLeaders ??= <LeaderLayer>{};
_debugPreviousLeaders!.add(_leader!);
_debugScheduleLeadersCleanUpCheck();
return _debugPreviousLeaders!.add(_leader!);
}
return true;
}());
@ -2127,14 +2127,10 @@ class LayerLink {
}
void _unregisterLeader(LeaderLayer leader) {
assert(_leader != null);
if (_leader == leader) {
_leader = null;
} else {
assert((){
_debugPreviousLeaders!.remove(leader);
return true;
}());
assert(_debugPreviousLeaders!.remove(leader));
}
}

View file

@ -176,6 +176,19 @@ void main() {
expect(leaderLayer.link, link2);
});
test('layer link attach/detach order should not crash app.', () {
renderer;
final LayerLink link = LayerLink();
final LeaderLayer leaderLayer1 = LeaderLayer(link: link);
final LeaderLayer leaderLayer2 = LeaderLayer(link: link);
final RenderView view = RenderView(configuration: const ViewConfiguration(), window: window);
leaderLayer1.attach(view);
leaderLayer2.attach(view);
leaderLayer2.detach();
leaderLayer1.detach();
expect(link.leader, isNull);
});
test('leader layers not dirty when connected to follower layer', () {
final ContainerLayer root = ContainerLayer()..attach(Object());

View file

@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
@ -1587,6 +1588,28 @@ void main() {
expect(() => element.widget, throwsA(isA<TypeError>()));
});
testWidgets('LayerLink can be swapped between parent and child container layers', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/96959.
final LayerLink link = LayerLink();
await tester.pumpWidget(_TestLeaderLayerWidget(
link: link,
child: const _TestLeaderLayerWidget(
child: Placeholder(),
)
));
expect(tester.takeException(), isNull);
// Swaps the layer link.
await tester.pumpWidget(_TestLeaderLayerWidget(
child: _TestLeaderLayerWidget(
link: link,
child: const Placeholder(),
),
));
expect(tester.takeException(), isNull);
});
testWidgets('Deactivate and activate are called correctly', (WidgetTester tester) async {
final List<String> states = <String>[];
Widget build([Key? key]) {
@ -2031,3 +2054,53 @@ class _EmptyElement extends Element {
@override
void performRebuild() {}
}
class _TestLeaderLayerWidget extends SingleChildRenderObjectWidget {
const _TestLeaderLayerWidget({
Key? key,
this.link,
Widget? child,
}) : super(key: key, child: child);
final LayerLink? link;
@override
_RenderTestLeaderLayerWidget createRenderObject(BuildContext context) {
return _RenderTestLeaderLayerWidget(
link: link,
);
}
@override
void updateRenderObject(BuildContext context, _RenderTestLeaderLayerWidget renderObject) {
renderObject.link = link;
}
}
class _RenderTestLeaderLayerWidget extends RenderProxyBox {
_RenderTestLeaderLayerWidget({
LayerLink? link,
RenderBox? child,
}) : _link = link,
super(child);
LayerLink? get link => _link;
LayerLink? _link;
set link(LayerLink? value) {
if (_link == value) {
return;
}
_link = value;
markNeedsPaint();
}
@override
bool get isRepaintBoundary => true;
@override
void paint(PaintingContext context, Offset offset) {
super.paint(context, offset);
if (_link != null) {
context.pushLayer(LeaderLayer(link: _link!, offset: offset),(_, __){}, Offset.zero);
}
}
}