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

Android如何在独立线程获取Sensor值 现有代码运行闪退如何修改

代码问题分析与修复方案

核心问题点

  • Message、Bundle全局复用异常:Android的Message属于池化复用对象,不能全局创建后反复发送,发送后的Message会被系统回收,再次修改复用会直接抛出运行时异常。
  • 子线程操作UI:你自定义的mSensorHandler绑定的是独立子线程的Looper,handleMessage回调运行在子线程,Android禁止子线程直接修改UI控件,会直接触发崩溃。
  • 缺少传感器监听解绑逻辑,会造成内存泄漏和后续异常。

修复后完整代码

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;

    SensorManager sensorManager;
    Sensor sensor;

    private HandlerThread mSensorThread;
    // 主线程Handler,用于UI更新操作
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private Handler mSensorHandler;
    private SensorEventListener sensorEventListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

        sensorEventListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
                    // 每次事件触发时从消息池获取新的Message,不全局复用
                    Message message = mSensorHandler.obtainMessage();
                    Bundle bundle = new Bundle();
                    bundle.putFloat("value", event.values[2]); // 取Z轴数值
                    message.setData(bundle);
                    mSensorHandler.sendMessage(message);
                }
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {

            }
        };

        mSensorThread = new HandlerThread("Sensor thread", Thread.MAX_PRIORITY);
        mSensorThread.start();
        mSensorHandler = new Handler(mSensorThread.getLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                Bundle bundle = msg.getData();
                float value = bundle.getFloat("value");
                // 切换到主线程更新UI
                mMainHandler.post(() -> binding.textView.setText(Float.toString(value)));
            }
        };
        // 直接复用已初始化的sensor对象,无需重复获取
        sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_UI, mSensorHandler);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 页面不可见时解绑传感器,减少资源消耗
        if (sensorManager != null && sensorEventListener != null) {
            sensorManager.unregisterListener(sensorEventListener);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 页面销毁时退出子线程,释放资源
        if (mSensorThread != null) {
            mSensorThread.quitSafely();
        }
    }
}

优化说明

  • 所有UI操作都切换到主线程执行,避免子线程操作UI的异常
  • 消息、Bundle改为每次事件触发时单独从消息池获取,避免复用已回收对象的异常
  • 新增生命周期监听逻辑,避免内存泄漏和后台不必要的资源消耗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:45:01