Skip to content

Commit e9db3cb

Browse files
romtsnclaude
andcommitted
ref(gestures): Simplify SentryGestureDetector resource lifecycle
Keep VelocityTracker alive across gesture cycles instead of obtain/recycle churn on every gesture. Add release() method called from SentryWindowCallback.stopTracking() to prevent native resource leaks when activity is destroyed mid-gesture. Also fix broken Javadoc @link to removed dependency, change onTouchEvent return to void, and remove redundant null check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 47117f4 commit e9db3cb

File tree

2 files changed

+14
-10
lines changed

2 files changed

+14
-10
lines changed

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureDetector.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
import org.jetbrains.annotations.Nullable;
1111

1212
/**
13-
* A lightweight gesture detector that replaces {@link
14-
* androidx.core.view.GestureDetectorCompat}/{@link GestureDetector} to avoid ANRs caused by
15-
* Handler/MessageQueue lock contention and IPC calls (FrameworkStatsLog.write).
13+
* A lightweight gesture detector that replaces {@code GestureDetectorCompat}/{@link
14+
* GestureDetector} to avoid ANRs caused by Handler/MessageQueue lock contention and IPC calls
15+
* (FrameworkStatsLog.write).
1616
*
1717
* <p>Only detects click (tap), scroll, and fling — the gestures used by {@link
1818
* SentryGestureListener}. Long-press, show-press, and double-tap detection (which require Handler
@@ -44,7 +44,7 @@ public final class SentryGestureDetector {
4444
this.maximumFlingVelocity = config.getScaledMaximumFlingVelocity();
4545
}
4646

47-
boolean onTouchEvent(final @NotNull MotionEvent event) {
47+
void onTouchEvent(final @NotNull MotionEvent event) {
4848
final int action = event.getActionMasked();
4949

5050
if (velocityTracker == null) {
@@ -94,7 +94,7 @@ boolean onTouchEvent(final @NotNull MotionEvent event) {
9494
case MotionEvent.ACTION_UP:
9595
if (isInTapRegion) {
9696
listener.onSingleTapUp(event);
97-
} else if (velocityTracker != null) {
97+
} else {
9898
final int pointerId = event.getPointerId(0);
9999
velocityTracker.computeCurrentVelocity(1000, maximumFlingVelocity);
100100
final float velocityX = velocityTracker.getXVelocity(pointerId);
@@ -105,22 +105,25 @@ boolean onTouchEvent(final @NotNull MotionEvent event) {
105105
listener.onFling(currentDownEvent, event, velocityX, velocityY);
106106
}
107107
}
108-
cleanup();
108+
endGesture();
109109
break;
110110

111111
case MotionEvent.ACTION_CANCEL:
112-
cleanup();
112+
endGesture();
113113
break;
114114
}
115-
116-
return false;
117115
}
118116

119-
private void cleanup() {
117+
/** Releases native resources. Call when the detector is no longer needed. */
118+
void release() {
119+
endGesture();
120120
if (velocityTracker != null) {
121121
velocityTracker.recycle();
122122
velocityTracker = null;
123123
}
124+
}
125+
126+
private void endGesture() {
124127
if (currentDownEvent != null) {
125128
currentDownEvent.recycle();
126129
currentDownEvent = null;

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryWindowCallback.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ private void handleTouchEvent(final @NotNull MotionEvent motionEvent) {
7373

7474
public void stopTracking() {
7575
gestureListener.stopTracing(SpanStatus.CANCELLED);
76+
gestureDetector.release();
7677
}
7778

7879
public @NotNull Window.Callback getDelegate() {

0 commit comments

Comments
 (0)