1

我正在製作一個基於方向和加速度計讀數(運動運動非常緩慢)來跟蹤運動運動的應用程序。我所擁有的是一種策略模式,即我有一個抽象類用於運動運動,具體的運動運動實現實際的事物。問題是,我正在產生線程來跟蹤我活動中onSensorChanged()方法的不同練習。因爲這將被稱爲很多次,我不知道我的代碼是否會產生儘可能多的線程。他們收集垃圾嗎?Android中的onSensorChanged()產生線程

代碼:

public class WorkoutBuddy extends Activity implements SensorEventListener { 

    TextView t1, t2, t3, t4, t5, t6, t7; 
    SensorManager sensorManager;; 
    private Sensor sensorAccelerometer; 
    private Sensor sensorMagneticField; 
    private float[] valuesAccelerometer; 
    private float[] valuesMagneticField; 
    private float[] valuesOrientation; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.exercise_buddy); 

     sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 
     sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
     sensorMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 

     valuesAccelerometer = new float[3]; 
     valuesMagneticField = new float[3]; 
     valuesOrientation = new float[3]; 

     matrixR = new float[9]; 
     matrixI = new float[9]; 
     matrixValues = new float[3]; 

     //mediaPlayer = MediaPlayer.create(this, R.raw.first_position_confirmation); 
    } 

    @Override 
    protected void onPause() { 
     sensorManager.unregisterListener(this,sensorAccelerometer); 
     sensorManager.unregisterListener(this,sensorMagneticField); 
     super.onPause(); 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 
     // TODO Auto-generated method stub 
    } 

    float[] orientation; 
    private float[] matrixR; 
    private float[] matrixI; 
    private float[] matrixValues; 

    @Override 
    public void onSensorChanged(SensorEvent event) { 


     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
      valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer); 
     } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
      valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField); 
     } 
     if (valuesAccelerometer != null && valuesMagneticField != null) { 
      SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField); 

      if(true){ 
       SensorManager.getOrientation(matrixR, matrixValues); 

       double azimuth = Math.toDegrees(matrixValues[0]); 
       double pitch = Math.toDegrees(matrixValues[1]); 
       double roll = Math.toDegrees(matrixValues[2]); 

       valuesOrientation[0]=(float) pitch; 
       valuesOrientation[1]=(float) roll; 
       valuesOrientation[0]=(float) azimuth; 


       Thread forExc1 = new Thread(new LeftShoulder(valuesAccelerometer, valuesOrientation, this)); 
       Thread forExc2 = new Thread(new RightShoulder(valuesAccelerometer, valuesOrientation, this)); 

       forExc1.run(); 
       forExc2.run(); 

      } 

     } 
    } 

    @Override 
    protected void onResume() { 
     sensorManager.registerListener(this,sensorAccelerometer,SensorManager.SENSOR_DELAY_NORMAL); 
     sensorManager.registerListener(this,sensorMagneticField,SensorManager.SENSOR_DELAY_NORMAL); 
     super.onResume(); 
    } 

    //Low pass filter used to smooth the sensor readings 
    protected float[] lowPass(float[] input, float[] output) { 
     float ALPHA = 0.25f; 
     if (output == null) return input;  
     for (int i=0; i<input.length; i++) { 
      output[i] = output[i] + ALPHA * (input[i] - output[i]); 
     } 
     return output; 
    } 


} 



package com.example.msapp2; 


public abstract class ExerciseMovement implements Runnable{ 
    protected float[] acc, ori; 
    protected boolean played = false; 

} 



package com.example.msapp2; 

import android.content.Context; 
import android.media.MediaPlayer; 

public class LeftShoulder extends ExerciseMovement { 

    MediaPlayer mediaPlayer; 
    public LeftShoulder(float[] accelerometer, float[] orientation, Context context){ 
     mediaPlayer = MediaPlayer.create(context, R.raw.first_position_confirmation); 
     acc = accelerometer; 
     //this.ori = orientation; 
    } 

    public void run(){ 
     if(acc[0]> -10 && acc[0] < -8.5 && !played){ 
      mediaPlayer.start(); 
      played = true; 
     } 
    } 


} 
+0

它已經有一段時間,因爲我做了任何Android,但你可能要檢查'Executor'類。該類旨在傳遞任務,併爲您執行線程池的所有管理。以下是您要查看的文檔。它也有一些例子。 http://developer.android.com/reference/java/util/concurrent/Executor.html – DavidAndroidDev

+0

此外,根據@rupps的答案,您可以通過檢查事件上的時間戳來控制最終創建的線程數量,如果它在你的應用中有意義的話,可能每隔幾秒只產生一次任務。 – DavidAndroidDev

回答

2

如果你只是覆蓋OnSensorChanged和輸出Log.d,你會看到它被稱爲數百,甚至數千次每秒。

我建議你採用相反的方法:創建只需一個線程在後臺處理不同的接收事件,然後從onSensorChanged提供此類線程。

在線程中實現一種事件隊列。假設成千上萬的事件不斷髮生。

類似:

 private class ShoulderMovementProcessorThread extends Thread { 

       ..... 

       // this will be called from the UI thread, just add event to the (synchronized) queue. 

       public void publish (int[] valuesAccelerometer, int[] valuesWhatever) { 

        add_event_to_queue(); 

       } 

       // this is the typical event loop where you read one from the queue, process it, then wait for the next 
       public void run() { 
        -> get event 
        -> process event 
        -> wait for next event 
       } 

     } 

     ShoulderMovementProcessorThread mShoulderProcessor=new ShoulderMovementProcessorThread(...); 

     @Override 
     public void onSensorChanged(SensorEvent event) { 
       decodeEvent (event); // fills up azimuth, roll, etc. 
       mShoulderProcessor.publish(valuesAccelerometer, valuesWhatever);   

     } 


     // decode an event 
     private void decodeEvent (SensorEvent event) { 

      if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
       valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer); 
      } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
       valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField); 
      } 
      if (valuesAccelerometer != null && valuesMagneticField != null) { 
       SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField); 

       if(true){ 
        SensorManager.getOrientation(matrixR, matrixValues); 

        double azimuth = Math.toDegrees(matrixValues[0]); 
        double pitch = Math.toDegrees(matrixValues[1]); 
        double roll = Math.toDegrees(matrixValues[2]); 

        valuesOrientation[0]=(float) pitch; 
        valuesOrientation[1]=(float) roll; 
        valuesOrientation[0]=(float) azimuth; 

       } 

      } 
     } 
+0

你能舉個例子嗎?我不完全明白你想說什麼 –

+0

我不知道如何將不斷變化的值傳遞給線程。 –

+2

@ user3000837:使用LinkedBlockingQueue。 – CommonsWare

0

我實施了類似的最近的東西:

public class DBWorkerThread implements Runnable 
{ 
    private SensorEnum sensorType; 
    private LinkedBlockingQueue<float[]> sensorData; 
    private DBService dbService; 

    public DBWorkerThread(SensorEnum type, DBService dbService) 
    { 
     this.sensorType = type; 
     this.dbService = dbService; 
     this.sensorData = new LinkedBlockingQueue<float[]>(); 
    } 

    /** 
    * Add data to queue 
    * @param values 
    */ 
    public void addDataToProcess(float[] values) 
    { 
     if (sensorData.size() < sensorData.remainingCapacity()) 
     { 
      try 
      { 
       this.sensorData.put(values); 
      } 
      catch (Exception ex) 
      { 
       LogService.log("Error adding queue: " + ex.getMessage()); 
      } 
      LogService.log("Added to queue. Size: " + sensorData.size()); 
     } 
    } 

    /** 
    * Processes queue of data 
    */ 
    @Override 
    public void run() 
    { 
     // Moves the current Thread into the background 
     android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); 

     while (sensorData.size() > 0) 
     { 
      try 
      { 
       float[] values = sensorData.take(); 
       storeData(values); 
      } 
      catch (Exception ex) 
      { 
       LogService.log("Error in queue: " + ex.getMessage()); 
      } 
     } 
    } 

    /** 
    * Store data to database 
    * @param values 
    */ 
    private void storeData(float[] values) 
    { 
     // store data 
    } 
} 

希望這有助於