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
相关产品推荐
相关产品推荐

