2010-07-20 18 views
13

Bu temel bir soru gibi görünüyor, ancak bir süre aradıktan sonra ve onunla oynadıktan sonra, bazı yardımların takdir edileceği noktaya geldim. SensorEventListener ürününün kullanıcı arabiriminden ayrı bir iş parçacığında çalıştırılmasını isterim. Böylece, olaylar geldiğinde oluşması gereken hesaplamalar, kullanıcı arabirimini yavaşlatmaz.SensorEventListener ayrı iş parçacığında

Benim son girişim gibi görünüyor: In

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 
     } 
    } 

aktivite (veya hizmetin) onCreate(), bir SensorThread nesne oluşturmak ve start() yöntemini çağırın. Beklendiği gibi, hata ayıklama günlüğü yeni iş parçacığında "RunTag" girdisini gösterir. Ama onSensorChanged() 'ın "ListenerTag", nesnesi yeni iş parçacığında başlatılmış olsa bile, ana iş parçacığında çalışıyor. Bunu nasıl değiştirebilirim?

+0

[Acclerometre Sensörünün Ayrı Dişte olası kopyası] (http://stackoverflow.com/questions/17513352/acclerometer-sensor-in-separate-thread) –

cevap

6

SensorManager, onSensorChanged yöntemini çağırmaktan sorumludur ve registerListener'ın bu ayrı iş parçacığında çağrılmasının aslında bir fark yaratacağını düşünmüyorum. Yapılması en kolay şey, muhtemelen tüm ağır kaldırma işlemini ayrı bir iş parçacığına aktararak, hemenSensorChanged dönüşünü yapmaktır. Ya da belki de böyle şeyler yapmanın resmi “doğru yolu” gibi görünen bir ASyncTask'a.

+0

Fikir için teşekkürler. 8-bit mikro dünyadan geliyorum, bu yüzden benim düşüncemi biraz değiştirmem gerekebilir. Sensör her değiştiğinde yeni görevlerin ayrılması (örnek hızına bağlı olarak saniyede 5-50x) bir atık gibi görünür. – Thinman

+2

Eh, belki de sadece belirli durumlarda görevi tahsis ederdi. Örneğin, sensör okumasını hafızaya kaydeder ve daha sonra okumanın bazı eşikten daha fazla değişip değişmediğini onSensorChanged yönteminde kontrol eder. Eğer varsa, o zaman ASyncTask başlar.Gerçekten Android ile çalışmaya başladım, bu yüzden en iyi neyin işe yaradığını bilmiyorum. – MatrixFrog

+0

OnSensorChanged, ASyncTask uygulamasında gerçekten çalışmalıdır - ana sınıfınız bir arka plan hizmeti olsa bile (durumumda olduğu gibi), yöntemden yeterince hızlı dönmezse, bir sonraki SensorManager çağrısı yapamazsınız ... – Radu

12

Sensör olayını arka plan iş parçacığında alabilirsiniz.

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

yerine, ikincil bir dişe atıfta bulunan bir işleyici ile bildirebilirsiniz. Bir dişin çalışma döngüsü aşağıdaki gibidir: diğerleri hala bilmek istiyorum

... 
run { 
    Looper.prepare; 
    Handler handler = new Handler(); 
    ... 
    mSensorManager.registerListener(msl, mSensor, SensorManager.SENSOR_DELAY_UI, handler); 
    Looper.loop(); 
} 
... 
+0

public void run() {... ve Looper.prepare(); – Slackware

+0

Veya android.os.HandlerThread'i kullanın ve bir İşleyici oluşturun: yeni İşleyici (yourHandlerThread.getLooper()) –

7

Biraz geç oldu ama, burada bunu başarmak için iyi bir yoldur. Her zaman olduğu gibi, multithreading yaparken, ne yaptığınızı bildiğinizden emin olun ve bu tuhaf hataları önlemek için doğru zaman ayırın. İyi eğlenceler!

Sınıf üyeler:

private HandlerThread mSensorThread; 
private Handler mSensorHandler; 
OnCreate içinde

veya kayıt: kaydını yaparken

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); 

, ayrıca yapın:

mSensorThread.quitSafely(); 
+0

belki de en iyi yanıt – Taranfx

+0

"Thread.MAX_PRIORITY", [HandlerThread Android Geliştiricileri] bölümünde önerildiği gibi "Process.THREAD_PRIORITY_MORE_FAVORABLE" olarak değiştirilmelidir (https://developer.android.com/reference/android/os/HandlerThread.html#HandlerThread(java.lang.String,%20int) "[...] Sağlanan değer, java.lang.Thread. " –

0

geçerli iş parçacığı işleyicisi oluşturma Kayıt olmayı nerede dinleyiciniz ve üçüncü argüman olarak dinleyiciye aktarın.

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; 

    } 
1

İş parçacığının işleyicisini alın ve dinleyiciyi bu iş parçacığına kaydedin. Örneğin:

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(); 
} 

umutları bu size yardımcı olacaktır.

İlgili konular