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

Jetpack Compose在Redmi设备触发Offset is unspecified异常咨询

问题说明

项目开发过程中会高频触发如下致命崩溃:

Fatal Exception: java.lang.IllegalStateException
Offset is unspecified
  • 复现设备特征:仅在Redmi品牌的手机、平板设备上出现
  • 影响范围:Jetpack Compose 1.1.0 到最新的1.2.0-beta03版本均存在该问题,无法通过切换Compose版本规避
  • 崩溃触发链路:触摸事件分发阶段,AndroidComposeView 计算窗口位置偏移时拿到了未初始化的Offset值,直接抛出异常,完整堆栈如下:
androidx.compose.ui.geometry.Offset.getX-impl (Offset.java:28)
androidx.compose.ui.platform.AndroidComposeView.recalculateWindowPosition (AndroidComposeView.java:2)
androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc (AndroidComposeView.java:6)
androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent (AndroidComposeView.java:62)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3088)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2781)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3088)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2781)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3088)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2781)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3088)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2781)
com.android.internal.policy.DecorView.superDispatchTouchEvent (DecorView.java:496)
com.android.internal.policy.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1853)
android.app.Activity.dispatchTouchEvent (Activity.java:4072)
com.android.internal.policy.DecorView.dispatchTouchEvent (DecorView.java:454)
android.view.View.dispatchPointerEvent (View.java:13744)
android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:5601)
android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:5401)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:4902)
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:4955)
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:4921)
android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:5061)
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:4929)
android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:5118)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:4902)
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:4955)
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:4921)
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:4929)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:4902)
android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:7654)
android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:7623)
android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:7584)
android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:7785)
android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:251)
android.view.InputEventReceiver.nativeConsumeBatchedInputEvents (InputEventReceiver.java)
android.view.InputEventReceiver.consumeBatchedInputEvents (InputEventReceiver.java:213)
android.view.ViewRootImpl.doConsumeBatchedInput (ViewRootImpl.java:7730)
android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run (ViewRootImpl.java:7809)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:1031)
android.view.Choreographer.doCallbacks (Choreographer.java:854)
android.view.Choreographer.doFrame (Choreographer.java:782)
android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1016)
android.os.Handler.handleCallback (Handler.java:883)
android.os.Handler.dispatchMessage (Handler.java:100)
android.os.Looper.loop (Looper.java:223)
android.app.ActivityThread.main (ActivityThread.java:7562)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:539)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:950)
根因说明

大量开发者都在Redmi/小米设备上遇到过相同问题,这是MIUI系统的兼容性bug:MIUI修改了原生触摸事件上报逻辑,在批量投递触摸事件的场景下,会偶发传入x/y坐标为NaN的无效MotionEvent,Compose内部recalculateWindowPosition方法没有对这类非法值做容错,直接读取Offset坐标时就会触发Offset is unspecified的崩溃,和Compose版本没有直接关系,所以切换版本无法解决。

可行解决方案

目前有两个经过线上大流量验证的规避方案,不会影响正常触摸交互:

  • 方案1:自定义安全ComposeView,在事件分发入口拦截无效触摸事件,代码如下:
class SafeComposeView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : ComposeView(context, attrs) {
    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        ev?.let {
            if (it.x.isNaN() || it.y.isNaN()) {
                return true
            }
        }
        return super.dispatchTouchEvent(ev)
    }
}

项目中所有使用Compose的位置替换为该自定义View即可。

  • 方案2:如果是直接通过ComponentActivity.setContent接入Compose,可以直接在Activity层重写dispatchTouchEvent做全局拦截,不需要替换所有ComposeView:
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    ev?.let {
        if (it.x.isNaN() || it.y.isNaN()) {
            return true
        }
    }
    return super.dispatchTouchEvent(ev)
}

补充:如果项目中同时存在原生View和Compose混合的页面,优先用Activity层全局拦截的方案,覆盖范围更全,不会漏掉其他位置触发的同类崩溃。

内容的提问来源于stack exchange,提问作者Ильин Павел

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:54:17