Skip to content

Commit

Permalink
Check whether slider is mounted before interaction, no-op if unmounte…
Browse files Browse the repository at this point in the history
…d (#113556)

* Check whether slider is unmounted before interaction

* Update slider.dart

* Update Slider

* Add test

* Update slider_test.dart

* Update packages/flutter/test/material/slider_test.dart

Co-authored-by: Taha Tesser <tessertaha@gmail.com>

Co-authored-by: Taha Tesser <tessertaha@gmail.com>
  • Loading branch information
liumcse and TahaTesser committed Jan 19, 2023
1 parent 3e71e0c commit 213b3cb
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/flutter/lib/src/material/slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,9 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {

@override
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (!_state.mounted) {
return;
}
assert(debugHandleEvent(event, entry));
if (event is PointerDownEvent && isInteractive) {
// We need to add the drag first so that it has priority.
Expand Down
55 changes: 55 additions & 0 deletions packages/flutter/test/material/slider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3437,6 +3437,61 @@ void main() {
);
}, variant: TargetPlatformVariant.desktop());

testWidgets('Event on Slider should perform no-op if already unmounted', (WidgetTester tester) async {
// Test covering crashing found in Google internal issue b/192329942.
double value = 0.0;
final ValueNotifier<bool> shouldShowSliderListenable =
ValueNotifier<bool>(true);

await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Material(
child: Center(
child: ValueListenableBuilder<bool>(
valueListenable: shouldShowSliderListenable,
builder: (BuildContext context, bool shouldShowSlider, _) {
return shouldShowSlider
? Slider(
value: value,
onChanged: (double newValue) {
setState(() {
value = newValue;
});
},
)
: const SizedBox.shrink();
},
),
),
);
},
),
),
),
);

final TestGesture gesture = await tester
.startGesture(tester.getRect(find.byType(Slider)).centerLeft);

// Intentioanlly not calling `await tester.pumpAndSettle()` to allow drag
// event performed on `Slider` before it is about to get unmounted.
shouldShowSliderListenable.value = false;

await tester.drag(find.byType(Slider), const Offset(1.0, 0.0));
await tester.pumpAndSettle();

expect(value, equals(0.0));

// This is supposed to trigger animation on `Slider` if it is mounted.
await gesture.up();

expect(tester.takeException(), null);
});

group('Material 2', () {
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
// is turned on by default, these tests can be removed.
Expand Down

0 comments on commit 213b3cb

Please sign in to comment.