Fix asserts in Draggable dismounting (#4644)
In writing a test for #1927, I found a number of bugs in how Draggable shuts down. Previously it would leak its recongizer. Now it disposes its recognizer and the recognizer knows how to be disposed cleanly. Fixes #1927
This commit is contained in:
parent
cff31a3f6d
commit
b3780ebc16
@ -5,6 +5,8 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui' show Point, Offset;
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'arena.dart';
|
||||
import 'binding.dart';
|
||||
import 'constants.dart';
|
||||
@ -147,7 +149,9 @@ abstract class MultiDragPointerState {
|
||||
}
|
||||
|
||||
/// Releases any resources used by the object.
|
||||
@mustCallSuper
|
||||
void dispose() {
|
||||
_arenaEntry?.resolve(GestureDisposition.rejected);
|
||||
assert(() { _pendingDelta = null; return true; });
|
||||
}
|
||||
}
|
||||
@ -258,14 +262,14 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten
|
||||
assert(_pointers != null);
|
||||
assert(_pointers.containsKey(pointer));
|
||||
GestureBinding.instance.pointerRouter.removeRoute(pointer, _handleEvent);
|
||||
_pointers[pointer].dispose();
|
||||
_pointers.remove(pointer);
|
||||
_pointers.remove(pointer).dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (int pointer in _pointers.keys)
|
||||
for (int pointer in _pointers.keys.toList())
|
||||
_removeState(pointer);
|
||||
assert(_pointers.isEmpty);
|
||||
_pointers = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
@ -262,6 +262,12 @@ class _DraggableState<T> extends State<DraggableBase<T>> {
|
||||
_recognizer = config.createRecognizer(_startDrag);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_recognizer.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
GestureRecognizer _recognizer;
|
||||
int _activeCount = 0;
|
||||
|
||||
|
@ -871,6 +871,75 @@ void main() {
|
||||
await tester.pump();
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('Draggable disposes recognizer', (WidgetTester tester) async {
|
||||
bool didTap = false;
|
||||
await tester.pumpWidget(new Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
new OverlayEntry(
|
||||
builder: (BuildContext context) => new GestureDetector(
|
||||
onTap: () {
|
||||
didTap = true;
|
||||
},
|
||||
child: new Draggable<dynamic>(
|
||||
child: new Container(
|
||||
decoration: new BoxDecoration(
|
||||
backgroundColor: new Color(0xFFFFFF00)
|
||||
)
|
||||
),
|
||||
feedback: new Container(
|
||||
width: 100.0,
|
||||
height: 100.0,
|
||||
decoration: new BoxDecoration(
|
||||
backgroundColor: new Color(0xFFFF0000)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
));
|
||||
|
||||
await tester.startGesture(const Point(10.0, 10.0));
|
||||
expect(didTap, isFalse);
|
||||
|
||||
// This tears down the draggable without terminating the gesture sequence,
|
||||
// which used to trigger asserts in the multi-drag gesture recognizer.
|
||||
await tester.pumpWidget(new Container(key: new UniqueKey()));
|
||||
expect(didTap, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('Draggable plays nice with onTap', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
new OverlayEntry(
|
||||
builder: (BuildContext context) => new GestureDetector(
|
||||
onTap: () { /* registers a tap recognizer */ },
|
||||
child: new Draggable<dynamic>(
|
||||
child: new Container(
|
||||
decoration: new BoxDecoration(
|
||||
backgroundColor: new Color(0xFFFFFF00)
|
||||
)
|
||||
),
|
||||
feedback: new Container(
|
||||
width: 100.0,
|
||||
height: 100.0,
|
||||
decoration: new BoxDecoration(
|
||||
backgroundColor: new Color(0xFFFF0000)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
));
|
||||
|
||||
TestGesture firstGesture = await tester.startGesture(const Point(10.0, 10.0), pointer: 24);
|
||||
TestGesture secondGesture = await tester.startGesture(const Point(10.0, 20.0), pointer: 25);
|
||||
|
||||
await firstGesture.moveBy(new Offset(100.0, 0.0));
|
||||
await secondGesture.up();
|
||||
});
|
||||
}
|
||||
|
||||
class DragTargetData { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user