简体   繁体   English

Android-确定指南针中的内存泄漏(SensorManager)

[英]Android - Determine Memory Leak in Compass (SensorManager)

I implemented a simple compass class using a singleton pattern. 我使用单例模式实现了一个简单的指南针类。 Once I registered the accelerometer and magnetometer listener with the sensor manager the memory consumption is increasing. 一旦我向传感器管理器注册了加速度计和磁力计监听器,内存消耗就会增加。 My GPS class is very similar to the compass class and there I have no problems regarding memory leaks.I placed a breakpoint in the onSensorChanged method and the the allocated memory is increases by 0,01 MB every 5 calls. 我的GPS类与指南针类非常相似,并且我对内存泄漏没有任何问题。我在onSensorChanged方法中放置了一个断点,并且每5次调用分配的内存增加了0.01 MB。 I will add the corresponding code below. 我将在下面添加相应的代码。 Maybe anyone got an idea what is going wrong. 也许有人知道出了什么问题。 Maybe there is no problem and its normal, that the memory is slightly increasing? 也许内存有一点增加是正常的,这没有问题,这是正常的吗?

Main 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 );
    }
    [...]
}

Compass 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;
    }
    [...]
}

Thanks in Advance! 提前致谢!

Each time 每一次

this.mSensorManager = (SensorManager) context.getSystemService( Context.SENSOR_SERVICE );

gets called, the instance of your current MainActivity gets tied to your singleton class. 被调用时,当前MainActivity的实例将与您的singleton类联系在一起。 Probably your GPS class would cause the same Memory leak but not as fast as this one. 您的GPS类可能会导致相同的内存泄漏,但速度不及此速度。

What you do here is bad design. 您在这里所做的是糟糕的设计。 Especially using the singleton class in an Activity. 特别是在Activity中使用单例类。 Refactor your code like this: 像这样重构代码:

  1. Learn about Service in Androids documentation 在Android文档中了解Service
  2. Put the sensor stuff in a service. 将传感器塞入服务中。
  3. In your service's onCreate method, use its context to get the system services for GPS and compass 在服务的onCreate方法中,使用其上下文获取GPS和指南针的系统服务
  4. Unbind the system services in the onDestroy method of your service 用服务的onDestroy方法解除系统服务的绑定
  5. Use Broadcasting like the LocalBroadcastManager to pass data to other components like to your Activities LocalBroadcastManager一样使用Broadcasting将数据传递到其他组件,例如您的Activity

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM