Repository: flutter
Issue: GestureDetector.onTapCancel is called during build phase, causing setState error unexpectedly
Labels: framework,f: gestures,has reproducible steps,P2,team-framework,triaged-framework,found in release: 3.27,found in release: 3.28

### Steps to reproduce

1. run the sample code below
2. press grey box
3. remove grey box by rebuilding (in the sample code, this will be done using `Timer`)
4. `onTapCancel` is called, where I call `setState()` inside.
5. the error below happens.

### Expected results

No error occurs, meaning `onTapCancel` should be called outside of the rebuilding process.

### Actual results

The error below happened.

```console
════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
setState() or markNeedsBuild() called when widget tree was locked.
This TapCancelDemo widget cannot be marked as needing to build because the framework is locked.
The widget on which setState() or markNeedsBuild() was called was: TapCancelDemo
    state: _TapCancelDemoState#27489

When the exception was thrown, this was the stack:
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5193:9)
framework.dart:5193
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5203:6)
framework.dart:5203
#2      State.setState (package:flutter/src/widgets/framework.dart:1224:15)
framework.dart:1224
```

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: TapCancelDemo()));

class TapCancelDemo extends StatefulWidget {
  const TapCancelDemo({super.key});

  @override
  State<TapCancelDemo> createState() => _TapCancelDemoState();
}

class _TapCancelDemoState extends State<TapCancelDemo> {
  String? _message;
  bool _isVisible = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          if (_isVisible)
            Expanded(
              child: GestureDetector(
                onTapCancel: () {
                  setState(() => _message = 'onTapCancel');
                },
                onTapDown: (details) {
                  setState(() => _message = 'onTapDown');
                  Timer(const Duration(milliseconds: 100), () {
                    // remove the widget after 100ms
                    setState(() => _isVisible = false);
                  });
                },
                child: Container(
                  margin: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(16),
                    color: Colors.grey,
                  ),
                  child: const Center(
                    child: Text('Tap me'),
                  ),
                ),
              ),
            ),
          const SizedBox(height: 32),
          Text(_message ?? ''),
          const SizedBox(height: 32),
        ],
      ),
    );
  }
}
```

</details>


### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

https://github.com/user-attachments/assets/cf9ceed8-87a8-4707-b8f9-a8c7107ec10f

</details>

### Logs

<details open><summary>Logs</summary>

```console

════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
setState() or markNeedsBuild() called when widget tree was locked.
This TapCancelDemo widget cannot be marked as needing to build because the framework is locked.
The widget on which setState() or markNeedsBuild() was called was: TapCancelDemo
    state: _TapCancelDemoState#f8162

When the exception was thrown, this was the stack:
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5193:9)
framework.dart:5193
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5203:6)
framework.dart:5203
#2      State.setState (package:flutter/src/widgets/framework.dart:1224:15)
framework.dart:1224
#3      _TapCancelDemoState.build.<anonymous closure> (package:example/reorderable_page.dart:29:19)
reorderable_page.dart:29
#4      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:351:24)
recognizer.dart:351
#5      TapGestureRecognizer.handleTapCancel (package:flutter/src/gestures/tap.dart:680:11)
tap.dart:680
#6      BaseTapGestureRecognizer._checkCancel (package:flutter/src/gestures/tap.dart:318:5)
tap.dart:318
#7      BaseTapGestureRecognizer.resolve (package:flutter/src/gestures/tap.dart:266:7)
tap.dart:266
#8      OneSequenceGestureRecognizer.dispose (package:flutter/src/gestures/recognizer.dart:469:5)
recognizer.dart:469
#9      PrimaryPointerGestureRecognizer.dispose (package:flutter/src/gestures/recognizer.dart:762:11)
recognizer.dart:762
#
```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
$ fvm flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.27.0, on macOS 14.3.1 23D60 darwin-arm64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] Android Studio (version 2022.2)
[✓] VS Code (version 1.95.3)
[✓] VS Code (version 1.61.2)
[✓] Connected device (4 available)
[✓] Network resources

• No issues found!
```

</details>