Published on

WillPopScope is now PopScope in Flutter

Authors

If you've handled back button interactions in Flutter, you've likely used WillPopScope. As of Flutter 3.12+, this widget has been deprecated in favor of PopScope – but it isn’t just a simple rename. Let's explore what changed and why it matters.

From Reactive to Predictive Handling

Old Approach (WillPopScope):

WillPopScope(
  onWillPop: () async {
    // Your exit logic here
    return false; // Block navigation
  },
  child: MyScreen(),
)

This asynchronous model worked by intercepting back gestures as they happened.

New Reality (PopScope):

PopScope<Object?>(
  canPop: _shouldAllowExit,
  onPopInvokedWithResult: (bool didPop, Object? result) {
    if (!didPop) {
      showExitConfirmation(context);
    }
  },
  child: MyScreen(),
)

The key shift: canPop must be determined before the back gesture starts. This synchronous approach enables Android’s predictive back animations.

Why This Changed

  • Android 14 Compatibility: Modern Android requires apps to declare navigation permissions upfront for smooth predictive back gestures. The old reactive model breaks this flow.
  • State Management: PopScope forces explicit state management through canPop, making navigation logic more declarative.
  • Type Safety: The generic parameter in PopScope allows type-safe result handling:
PopScope<int>(
  onPopInvokedWithResult: (didPop, result) {
    print('Popped with value: ${result ?? 'none'}');
  }
)

Key Migration Steps

Replace the widget:

- WillPopScope(
+ PopScope(

Convert your logic accordingly:

bool _canExit = false;

// ...existing code...
PopScope(
  canPop: _canExit,
  onPopInvokedWithResult: (didPop, _) {
    if (!didPop) {
      showDialog(
        context: context,
        builder: (_) => ExitConfirmationDialog(
          onConfirm: () {
            setState(() => _canExit = true);
            Navigator.pop(context);
            Navigator.pop(context); // Exit after dialog
          }
        )
      );
    }
  },
  child: MyContent(),
)
// ...existing code...

Android Manifest Fix

For API 34+ devices, update your AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:enableOnBackInvokedCallback="false">

Tradeoffs to Consider

  • Multiple PopScopes require careful synchronization.
  • Result handling now uses type parameters.
  • Predictive back requires Flutter 3.14+ and Android 14.

Why Not Just Update WillPopScope?

The Flutter team chose a clean break to:

  • Avoid breaking existing apps.
  • Enforce the new predictive back paradigm.
  • Simplify migration (a simple search/replace works in many cases).

The Future of Navigation

While PopScope requires adjusting your mental model, it brings Flutter in line with modern Android navigation standards. The initial learning curve pays off in smoother user experiences and better compatibility with upcoming OS features.

For those struggling with migration, remember: the key difference is thinking in terms of "can I pop?" rather than "should I pop?". Once that clicks, PopScope becomes a powerful ally in crafting intuitive navigation flows.