diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 43b9b7106f..2483e11537 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -316,6 +316,8 @@ class _DragTargetState extends State> { void didLeave(dynamic data) { assert(_candidateData.contains(data) || _rejectedData.contains(data)); + if (!mounted) + return; setState(() { _candidateData.remove(data); _rejectedData.remove(data); @@ -324,6 +326,8 @@ class _DragTargetState extends State> { void didDrop(dynamic data) { assert(_candidateData.contains(data)); + if (!mounted) + return; setState(() { _candidateData.remove(data); }); diff --git a/packages/flutter/test/widget/draggable_test.dart b/packages/flutter/test/widget/draggable_test.dart index 76eb629361..dacf7b35a7 100644 --- a/packages/flutter/test/widget/draggable_test.dart +++ b/packages/flutter/test/widget/draggable_test.dart @@ -913,6 +913,7 @@ void main() { expect(didTap, isFalse); }); + // Regression test for https://github.com/flutter/flutter/issues/6128. testWidgets('Draggable plays nice with onTap', (WidgetTester tester) async { await tester.pumpWidget(new Overlay( initialEntries: [ @@ -944,6 +945,65 @@ void main() { await firstGesture.moveBy(new Offset(100.0, 0.0)); await secondGesture.up(); }); + + testWidgets('DragTarget does not set state when remove from the tree', (WidgetTester tester) async { + List events = []; + Point firstLocation, secondLocation; + + await tester.pumpWidget(new MaterialApp( + home: new Column( + children: [ + new Draggable( + data: 1, + child: new Text('Source'), + feedback: new Text('Dragging') + ), + new DragTarget( + builder: (BuildContext context, List data, List rejects) { + return new Text('Target'); + }, + onAccept: (int data) { + events.add('drop'); + } + ), + ] + ) + )); + + expect(events, isEmpty); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Target'), findsOneWidget); + + expect(events, isEmpty); + await tester.tap(find.text('Source')); + expect(events, isEmpty); + + firstLocation = tester.getCenter(find.text('Source')); + TestGesture gesture = await tester.startGesture(firstLocation, pointer: 7); + await tester.pump(); + + await tester.pump(const Duration(seconds: 20)); + + secondLocation = tester.getCenter(find.text('Target')); + await gesture.moveTo(secondLocation); + await tester.pump(); + + await tester.pumpWidget(new MaterialApp( + home: new Column( + children: [ + new Draggable( + data: 1, + child: new Text('Source'), + feedback: new Text('Dragging') + ), + ] + ) + )); + + expect(events, isEmpty); + await gesture.up(); + await tester.pump(); + }); } class DragTargetData { }