Unverified Commit 28ca7bd7 authored by chunhtai's avatar chunhtai Committed by GitHub

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

parent 62e74561
...@@ -2118,8 +2118,8 @@ class LayerLink { ...@@ -2118,8 +2118,8 @@ class LayerLink {
assert((){ assert((){
if (_leader != null) { if (_leader != null) {
_debugPreviousLeaders ??= <LeaderLayer>{}; _debugPreviousLeaders ??= <LeaderLayer>{};
_debugPreviousLeaders!.add(_leader!);
_debugScheduleLeadersCleanUpCheck(); _debugScheduleLeadersCleanUpCheck();
return _debugPreviousLeaders!.add(_leader!);
} }
return true; return true;
}()); }());
...@@ -2127,14 +2127,10 @@ class LayerLink { ...@@ -2127,14 +2127,10 @@ class LayerLink {
} }
void _unregisterLeader(LeaderLayer leader) { void _unregisterLeader(LeaderLayer leader) {
assert(_leader != null);
if (_leader == leader) { if (_leader == leader) {
_leader = null; _leader = null;
} else { } else {
assert((){ assert(_debugPreviousLeaders!.remove(leader));
_debugPreviousLeaders!.remove(leader);
return true;
}());
} }
} }
......
...@@ -176,6 +176,19 @@ void main() { ...@@ -176,6 +176,19 @@ void main() {
expect(leaderLayer.link, link2); 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', () { test('leader layers not dirty when connected to follower layer', () {
final ContainerLayer root = ContainerLayer()..attach(Object()); final ContainerLayer root = ContainerLayer()..attach(Object());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -1587,6 +1588,28 @@ void main() { ...@@ -1587,6 +1588,28 @@ void main() {
expect(() => element.widget, throwsA(isA<TypeError>())); 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 { testWidgets('Deactivate and activate are called correctly', (WidgetTester tester) async {
final List<String> states = <String>[]; final List<String> states = <String>[];
Widget build([Key? key]) { Widget build([Key? key]) {
...@@ -2031,3 +2054,53 @@ class _EmptyElement extends Element { ...@@ -2031,3 +2054,53 @@ class _EmptyElement extends Element {
@override @override
void performRebuild() {} 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);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment