SensorEventListener в отдельном потоке - PullRequest
14 голосов
/ 20 июля 2010

Это кажется базовым вопросом, но после некоторого поиска и игры с ним я пришел к тому, что некоторая помощь будет признательна. Я бы хотел, чтобы SensorEventListener запускался в отдельном потоке от пользовательского интерфейса, чтобы вычисления, которые должны выполняться при поступлении событий, не замедляли работу пользовательского интерфейса.

Моя последняя попытка выглядит так:

class SensorThread extends Thread {
    SensorManager mSensorManager;
    Sensor mSensor;

    public void run() {
        Log.d( "RunTag", Thread.currentThread().getName() ); // To display thread
        mSensorManager = (SensorManager)getSystemService( SENSOR_SERVICE  );
        mSensor = mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
        MySensorListener msl = new MySensorListener();
        mSensorManager.registerListener(msl, mSensor, SensorManager.SENSOR_DELAY_UI );
    }

    private class MySensorListener implements SensorEventListener {
        public void onAccuracyChanged (Sensor sensor, int accuracy) {}
        public void onSensorChanged(SensorEvent sensorEvent) {
            Log.d( "ListenerTag", Thread.currentThread().getName() ); // To display thread
        }
    }

В onCreate () действия (или службы) я создаю объект SensorThread и вызываю его метод start (). Как и следовало ожидать, журнал отладки показывает запись «RunTag» в новом потоке. Но «ListenerTag» onSensorChanged () работает в основном потоке, даже если его объект создан в новом потоке. Как мне это изменить?

Ответы [ 5 ]

14 голосов
/ 15 января 2016

Немного поздно, но если другие все еще хотят знать, вот хороший способ достичь этого.Как всегда при многопоточности, убедитесь, что вы знаете, что делаете, и не торопитесь, чтобы все правильно, чтобы избежать этих странных ошибок.Веселитесь!

Члены класса:

private HandlerThread mSensorThread;
private Handler mSensorHandler;

в OnCreate или при регистрации:

mSensorThread = new HandlerThread("Sensor thread", Thread.MAX_PRIORITY);
mSensorThread.start();
mSensorHandler = new Handler(mSensorThread.getLooper()) //Blocks until looper is prepared, which is fairly quick
yourSensorManager.registerListener(yourListener, yourSensor, interval, mSensorHandler);

При отмене регистрации также выполните:

mSensorThread.quitSafely();
13 голосов
/ 20 июля 2011

Вы можете получить событие датчика в фоновом потоке. Вместо

mSensorManager.registerListener(msl, mSensor, SensorManager.SENSOR_DELAY_UI );

Вы можете объявить это с помощью обработчика, ссылающегося на вторичный поток. Цикл выполнения потока выглядит следующим образом:

...
run {
    Looper.prepare;
    Handler handler = new Handler();
    ...
    mSensorManager.registerListener(msl, mSensor, SensorManager.SENSOR_DELAY_UI, handler );
    Looper.loop();
}
...
6 голосов
/ 20 июля 2010

Похоже, что SensorManager фактически отвечает за вызов метода onSensorChanged, и я не думаю, что тот факт, что registerListener вызывается в этом отдельном потоке, будет иметь какое-то значение. Возможно, проще всего сделать мгновенный возврат onSensorChanged, передав всю тяжелую работу отдельному потоку. Или, возможно, для ASyncTask, который, кажется, является официальным «правильным способом» делать такие вещи.

1 голос
/ 18 июня 2016

Получите обработчик потока и зарегистрируйте слушателя в этом потоке. Например:

public void run() {
    Sensor sensor = this.sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
    Looper.prepare();
    Handler gHandler = new Handler();
    this.sensorManager.registerListener(gravitySensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL, gHandler);
    Looper.loop();
}

надеется, что это поможет вам.

0 голосов
/ 17 марта 2016

Создайте обработчик для текущего потока, в котором вы регистрируете слушателя, и передайте его слушателю в качестве третьего аргумента.

public void run() {
    Log.d( "RunTag", Thread.currentThread().getName() ); // To display thread
    mSensorManager = (SensorManager)getSystemService( SENSOR_SERVICE  );
    mSensor = mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
    MySensorListener msl = new MySensorListener();
    Looper.perpare;
    Handler hndlr = new Handler();

    mSensorManager.registerListener(msl, mSensor, 
     SensorManager.SENSOR_DELAY_UI, hndlr);
    Looper.loop;

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...