You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级compileSdkVersion至33后,onScroll参数null引发崩溃问题排查

问题:GestureDetector监听ScrollView滚动时的NullPointerException问题

我用GestureDetector捕获ScrollView的滚动事件,代码如下:

val gestureDetector = GestureDetector(this.fragment.activity, ScrollGestureListener(scrollView))
scrollView.setOnTouchListener(OnTouchListener { view, event ->
    gestureDetector.onTouchEvent(event)
    return@OnTouchListener false
})

internal inner class ScrollGestureListener(view: View) : GestureDetector.SimpleOnGestureListener() {
    override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
        this@DocumentViewer.onDrag()
        return true
    }
}

在compileSdkVersion为30时,应用会因onScroll的第一个参数始终为null而崩溃,我通过将第一个参数设为可空类型解决了该问题:

override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {

现在尝试将compileSdkVersion升级至33,上述代码无法编译;但如果恢复标准函数签名,滚动ScrollView时应用会再次崩溃。

排查过程

  • 看到一条评论指出:若有GestureDetector之外的组件消费ACTION_DOWN事件,就会出现此类崩溃,但我无法定位到相关组件。我曾在ScrollGestureListener中临时实现onDown方法,但它从未被调用,这似乎与ACTION_DOWN的评论相关。
  • 查看GestureDetector.java源码,发现传递给onScroll的第一个参数是mCurrentDownEvent,这也与ACTION_DOWN的评论相关。但在Android Studio中给GestureDetector.java加断点时,mCurrentDownEvent从未显示为null,且始终与第二个参数ev相同——GestureDetector只是将mCurrentDownEvent设为ev的副本。
  • 崩溃似乎发生在GestureDetector调用onScroll时,因为我的onScroll方法中的断点从未触发,即使移除onScroll的重写,调用父类实现也会崩溃。控制台报错如下:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.arlomedia.bandhelper, PID: 18797
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter e1
    at com.arlomedia.bandhelper.helpers.DocumentViewer$ScrollGestureListener.onScroll(Unknown Source:2)
    at android.view.GestureDetector.onTouchEvent(GestureDetector.java:788)
    at com.arlomedia.bandhelper.helpers.DocumentViewer.viewDocument$lambda-9(DocumentViewer.kt:1398)
    at com.arlomedia.bandhelper.helpers.DocumentViewer.$r8$lambda$kyj-4h2jNAIkIYOWSE7_HVetJAg(Unknown Source:0)
    at com.arlomedia.bandhelper.helpers.DocumentViewer$$ExternalSyntheticLambda7.onTouch(Unknown Source:6)
    at android.view.View.dispatchTouchEvent(View.java:15147)
  • 尝试在OnTouchListener中调用onTouchEvent前添加检查:
if (event != null) {
    gestureDetector.onTouchEvent(event)
}

但event从未为null,且查看其属性也无法判断是否会引发崩溃。

  • 另一个线索:只有当调用onTouchEvent时手指仍在屏幕上,才会触发onScroll。我尝试延迟调用:
val runnable = Runnable {
    gestureDetector.onTouchEvent(event)
}
App.instance.timerHandler.postDelayed(runnable, 1000)

若滚动后1秒内抬起手指,onScroll不会被调用,也不会崩溃;若手指保持在屏幕上超过1秒,onScroll会被调用并引发崩溃。

求助

我想到两种修复思路:在OnTouchListener中验证事件后再调用onTouchEvent,或找出导致GestureDetector向onScroll发送无效事件的原因,但目前已无头绪,希望得到解决方案。

内容的提问来源于stack exchange,提问作者arlomedia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:30:57