Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何解决SensorEventListener操作分离线程时出现的ANR问题?_Java_Android_Android Sensors_Android Thread_Android Handlerthread - Fatal编程技术网

Java 如何解决SensorEventListener操作分离线程时出现的ANR问题?

Java 如何解决SensorEventListener操作分离线程时出现的ANR问题?,java,android,android-sensors,android-thread,android-handlerthread,Java,Android,Android Sensors,Android Thread,Android Handlerthread,我是Java Android编程的noob(实际上我是计算机编程的noob)。我打算使SensorEventListener在一个线程中与服务时的主线程分离。OnSecorChanged方法在单独的线程中运行良好,然而,在操作服务后不久,ANR就会发生。尽管发生了ANR,但如果我没有在ANR发生时终止并按“等待”保持应用程序运行,那么应用程序将按照我的预期运行。 我一直试图找到如何解决这个问题很长时间,但我不能最终使我的应用程序停止发生ANR 这是我使用HandleThread的代码 publi

我是Java Android编程的noob(实际上我是计算机编程的noob)。我打算使SensorEventListener在一个线程中与服务时的主线程分离。OnSecorChanged方法在单独的线程中运行良好,然而,在操作服务后不久,ANR就会发生。尽管发生了ANR,但如果我没有在ANR发生时终止并按“等待”保持应用程序运行,那么应用程序将按照我的预期运行。 我一直试图找到如何解决这个问题很长时间,但我不能最终使我的应用程序停止发生ANR

这是我使用HandleThread的代码

public class SwingArmSensorService extends Service {
    private SensorManager mSensorManager;
    private Sensor mSensor;
    private AccelerometerListenerInService listener;
    private HandlerThread mSensorThread;
    private Handler mSensorHandler;
    private static SuperActivityUsingServiceMain activity;
    private int mSteps;
    private final String SWING_SENSOR_INTENT_STEP_DATA_NAME = "steps";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
        mSensorThread = new HandlerThread("Sensor Thread", Thread.MAX_PRIORITY); //
        mSensorThread.start(); //
        mSensorHandler = new Handler(mSensorThread.getLooper());
        listener = new AccelerometerListenerInService();
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(listener, mSensor, SensorManager.SENSOR_DELAY_NORMAL, mSensorHandler);
        mSteps = intent.getIntExtra(SWING_SENSOR_INTENT_STEP_DATA_NAME, 0);
        Looper.loop();

        ...
    }
    private class AccelerometerListenerInService implements SensorEventListener {
        private Handler mainHandler;

        private float previousY, currentY;
        private float x, y, z;

        private final float THRESHOLD = 10f;

        public AccelerometerListenerInService() {
            mainHandler = new Handler(Looper.getMainLooper());
        }

        @Override
        public void onSensorChanged(SensorEvent event) {
            x = event.values[0];
            y = event.values[1];
            z = event.values[2];
            currentY = y;

            if (Math.abs(currentY - previousY) > THRESHOLD) {
                mSteps++;
                // Handle UI at main thread here
                mainHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        activity.setTextView(mSteps);
                    }
                });
            }

            previousY = y;
        }

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

我打算只向您展示与代码问题相关的部分,但这是第一次发布问题堆栈溢出,因此如果我的代码太长,我很抱歉。

根本原因

在Android中,一个服务正在主线程上运行,该线程已经分配了一个循环器。在您的代码中,当服务启动时,它会在主线程上调用
Looper.prepare()
Looper.loop()
,这将导致应用程序出现意外行为

解决方案

SwingarmsSensorService
类中删除以下代码

if (Looper.myLooper() == null) {
    Looper.prepare();
}

Looper.loop();
因此,您的代码将是:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    mSensorThread = new HandlerThread("Sensor Thread", Thread.MAX_PRIORITY); //
    mSensorThread.start(); //
    mSensorHandler = new Handler(mSensorThread.getLooper());
    listener = new AccelerometerListenerInService();
    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mSensorManager.registerListener(listener, mSensor, SensorManager.SENSOR_DELAY_NORMAL, mSensorHandler);
    mSteps = intent.getIntExtra(SWING_SENSOR_INTENT_STEP_DATA_NAME, 0);
    ...
}

根本原因

在Android中,一个服务正在主线程上运行,该线程已经分配了一个循环器。在您的代码中,当服务启动时,它会在主线程上调用
Looper.prepare()
Looper.loop()
,这将导致应用程序出现意外行为

解决方案

SwingarmsSensorService
类中删除以下代码

if (Looper.myLooper() == null) {
    Looper.prepare();
}

Looper.loop();
因此,您的代码将是:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    mSensorThread = new HandlerThread("Sensor Thread", Thread.MAX_PRIORITY); //
    mSensorThread.start(); //
    mSensorHandler = new Handler(mSensorThread.getLooper());
    listener = new AccelerometerListenerInService();
    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mSensorManager.registerListener(listener, mSensor, SensorManager.SENSOR_DELAY_NORMAL, mSensorHandler);
    mSteps = intent.getIntExtra(SWING_SENSOR_INTENT_STEP_DATA_NAME, 0);
    ...
}

在这里,您可以阅读服务并了解其工作原理:在这里,您可以阅读服务并了解其工作原理: