Android - 确定 Compass 中的内存泄漏 (SensorManager)
Android - Determine Memory Leak in Compass (SensorManager)
我使用单例模式实现了一个简单的指南针 class。一旦我向传感器管理器注册了加速度计和磁力计侦听器,内存消耗就会增加。我的 GPS class 与指南针 class 非常相似,我没有内存方面的问题 leaks.I 在 onSensorChanged
方法中放置了一个断点,分配的内存增加了每 5 次调用 0.01 MB。我将在下面添加相应的代码。也许任何人都知道出了什么问题。可能没有问题正常,就是内存略有增加?
主要Activity
public class MainActivity extends ActionBarActivity {
[...]
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
this.mGPS = GPSTracker.getInstance();
this.mGPS.start( MainActivity.this );
this.mLocation = this.mGPS.getLatLng();
this.mCompass = CompassTracker.getInstance();
// uncomment the following line will stop the memory leak
this.mCompass.start( MainActivity.this );
}
[...]
}
罗盘Class
public class CompassTracker implements SensorEventListener {
[...]
/**
* The minimum time between updates in milliseconds.
*/
private static final int MIN_TIME_BW_UPDATES = 500; // 1 * 60 * 1000 -> 1 Minute
private void start( Context context ) {
this.mSensorManager = (SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
this.mAccelerometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
this.mMagnetometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_MAGNETIC_FIELD );
boolean enAcc = this.mSensorManager.registerListener( this, this.mAccelerometer, MIN_TIME_BW_UPDATES );
boolean enMag = this.mSensorManager.registerListener( this, this.mMagnetometer, MIN_TIME_BW_UPDATES );
if ( enAcc && enMag ) {
this.mStatus = States.ENABLED;
} else {
this.mStatus = States.NOT_AVAILABLE;
this.stop();
}
}
@Override
public void onSensorChanged( SensorEvent event ) {
final float alpha = 0.97f;
if ( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER ) {
this.mGravity[0] = alpha * this.mGravity[0] + ( 1 - alpha ) * event.values[0];
this.mGravity[1] = alpha * this.mGravity[1] + ( 1 - alpha ) * event.values[1];
this.mGravity[2] = alpha * this.mGravity[2] + ( 1 - alpha ) * event.values[2];
}
if ( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD ) {
this.mGeomagnetic[0] = alpha * this.mGeomagnetic[0] + ( 1 - alpha ) * event.values[0];
this.mGeomagnetic[1] = alpha * this.mGeomagnetic[1] + ( 1 - alpha ) * event.values[1];
this.mGeomagnetic[2] = alpha * this.mGeomagnetic[2] + ( 1 - alpha ) * event.values[2];
}
float R[] = new float[9];
float I[] = new float[9];
if ( SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic ) ) {
this.mOrientation = SensorManager.getOrientation( R, this.mOrientation );
}
// inform the listener
if( this.orientationChangedListener != null )
this.orientationChangedListener.onOrientationChanged( this.mOrientation );
}
/**
* Orientation listener
* @param orientationChangedListener
*/
public void setOrientationChangedListener( OrientationChangedListener orientationChangedListener ) {
this.orientationChangedListener = orientationChangedListener;
}
[...]
}
提前致谢!
每次
this.mSensorManager = (SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
被调用,您当前 MainActivity 的实例被绑定到您的单例 class。可能您的 GPS class 会导致相同的内存泄漏,但不会像这个那样快。
你在这里做的是糟糕的设计。特别是在 Activity 中使用单例 class。像这样重构您的代码:
- 在 Android 文档中了解
Service
- 将传感器的东西放在服务中。
- 在您服务的
onCreate
方法中,使用其上下文获取 GPS 和指南针的系统服务
- 在您的服务
onDestroy
方法中解绑系统服务
- 像
LocalBroadcastManager
一样使用广播将数据传递给其他组件,例如您的 Activity
我使用单例模式实现了一个简单的指南针 class。一旦我向传感器管理器注册了加速度计和磁力计侦听器,内存消耗就会增加。我的 GPS class 与指南针 class 非常相似,我没有内存方面的问题 leaks.I 在 onSensorChanged
方法中放置了一个断点,分配的内存增加了每 5 次调用 0.01 MB。我将在下面添加相应的代码。也许任何人都知道出了什么问题。可能没有问题正常,就是内存略有增加?
主要Activity
public class MainActivity extends ActionBarActivity {
[...]
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
this.mGPS = GPSTracker.getInstance();
this.mGPS.start( MainActivity.this );
this.mLocation = this.mGPS.getLatLng();
this.mCompass = CompassTracker.getInstance();
// uncomment the following line will stop the memory leak
this.mCompass.start( MainActivity.this );
}
[...]
}
罗盘Class
public class CompassTracker implements SensorEventListener {
[...]
/**
* The minimum time between updates in milliseconds.
*/
private static final int MIN_TIME_BW_UPDATES = 500; // 1 * 60 * 1000 -> 1 Minute
private void start( Context context ) {
this.mSensorManager = (SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
this.mAccelerometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
this.mMagnetometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_MAGNETIC_FIELD );
boolean enAcc = this.mSensorManager.registerListener( this, this.mAccelerometer, MIN_TIME_BW_UPDATES );
boolean enMag = this.mSensorManager.registerListener( this, this.mMagnetometer, MIN_TIME_BW_UPDATES );
if ( enAcc && enMag ) {
this.mStatus = States.ENABLED;
} else {
this.mStatus = States.NOT_AVAILABLE;
this.stop();
}
}
@Override
public void onSensorChanged( SensorEvent event ) {
final float alpha = 0.97f;
if ( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER ) {
this.mGravity[0] = alpha * this.mGravity[0] + ( 1 - alpha ) * event.values[0];
this.mGravity[1] = alpha * this.mGravity[1] + ( 1 - alpha ) * event.values[1];
this.mGravity[2] = alpha * this.mGravity[2] + ( 1 - alpha ) * event.values[2];
}
if ( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD ) {
this.mGeomagnetic[0] = alpha * this.mGeomagnetic[0] + ( 1 - alpha ) * event.values[0];
this.mGeomagnetic[1] = alpha * this.mGeomagnetic[1] + ( 1 - alpha ) * event.values[1];
this.mGeomagnetic[2] = alpha * this.mGeomagnetic[2] + ( 1 - alpha ) * event.values[2];
}
float R[] = new float[9];
float I[] = new float[9];
if ( SensorManager.getRotationMatrix( R, I, mGravity, mGeomagnetic ) ) {
this.mOrientation = SensorManager.getOrientation( R, this.mOrientation );
}
// inform the listener
if( this.orientationChangedListener != null )
this.orientationChangedListener.onOrientationChanged( this.mOrientation );
}
/**
* Orientation listener
* @param orientationChangedListener
*/
public void setOrientationChangedListener( OrientationChangedListener orientationChangedListener ) {
this.orientationChangedListener = orientationChangedListener;
}
[...]
}
提前致谢!
每次
this.mSensorManager = (SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
被调用,您当前 MainActivity 的实例被绑定到您的单例 class。可能您的 GPS class 会导致相同的内存泄漏,但不会像这个那样快。
你在这里做的是糟糕的设计。特别是在 Activity 中使用单例 class。像这样重构您的代码:
- 在 Android 文档中了解
Service
- 将传感器的东西放在服务中。
- 在您服务的
onCreate
方法中,使用其上下文获取 GPS 和指南针的系统服务 - 在您的服务
onDestroy
方法中解绑系统服务 - 像
LocalBroadcastManager
一样使用广播将数据传递给其他组件,例如您的 Activity