父类BaseActivity中SensorManager实现的内存泄漏问题排查与优化
问题描述
我已使用SensorManager处理屏幕方向,功能运行正常
但在BaseActivity中如下设置时出现了内存泄漏:
abstract class BaseActivity : AppCompatActivity(), SensorOrientationChangeNotifier.Listener { override fun onResume() { super.onResume() SensorOrientationChangeNotifier.getInstance(this)?.addListener(this) } override fun onPause() { super.onPause() SensorOrientationChangeNotifier.getInstance(this)?.remove(this) } }
SensorOrientationChangeNotifier.kt 代码
class SensorOrientationChangeNotifier private constructor(applicationContext: Context) { private val mListeners = ArrayList<WeakReference<Listener?>>(3) var orientation = 0 private set private val mSensorEventListener: SensorEventListener private val mSensorManager: SensorManager init { mSensorEventListener = NotifierSensorEventListener() mSensorManager = applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager } /** * Call on activity reset() */ private fun onResume() { mSensorManager.registerListener( mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL ) } /** * Call on activity onPause() */ private fun onPause() { mSensorManager.unregisterListener(mSensorEventListener) } private inner class NotifierSensorEventListener : SensorEventListener { override fun onSensorChanged(event: SensorEvent) { val x = event.values[0] val y = event.values[1] var newOrientation: Int = orientation if (x < 5 && x > -5 && y > 5) newOrientation = 0 else if (x < -5 && y < 5 && y > -5) newOrientation = 90 else if (x < 5 && x > -5 && y < -5) newOrientation = 180 else if (x > 5 && y < 5 && y > -5) newOrientation = 270 ///Timber.v("Matas_mOrientation = "+ newOrientation+" ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]"); if (orientation != newOrientation) { Timber.v("Matas_mOrientation-Orientation-> NEW") orientation = newOrientation notifyListeners() } else { ///Timber.v("Matas_mOrientation-Orientation-> OLD"); } } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} } interface Listener { fun onOrientationChange(orientation: Int) } fun addListener(listener: Listener) { if (get(listener) == null) // prevent duplications mListeners.add(WeakReference(listener)) if (mListeners.size == 1) { onResume() // this is the first client } } fun remove(listener: Listener) { val listenerWR = get(listener) remove(listenerWR) } private fun remove(listenerWR: WeakReference<Listener?>?) { if (listenerWR != null) mListeners.remove(listenerWR) if (mListeners.size == 0) { onPause() } } private operator fun get(listener: Listener): WeakReference<Listener?>? { for (existingListener in mListeners) if (existingListener.get() === listener) return existingListener return null } private fun notifyListeners() { val deadLiksArr = ArrayList<WeakReference<Listener?>>() for (wr in mListeners) { if (wr.get() == null) deadLiksArr.add(wr) else wr.get()!! .onOrientationChange(orientation) } // remove dead references for (wr in deadLiksArr) { mListeners.remove(wr) } } val isPortrait: Boolean = orientation == 0 || orientation == 180 val isLandscape: Boolean = !isPortrait companion object { val TAG = javaClass.simpleName private var mInstance: SensorOrientationChangeNotifier? = null fun getInstance(applicationContext: Context): SensorOrientationChangeNotifier? { if (mInstance == null) mInstance = SensorOrientationChangeNotifier(applicationContext) return mInstance } } }
我认为切换Activity时出现了context泄漏,问题根源在于单例对象mInstance始终不为空。
有没有更好的实现方案能在BaseActivity中避免内存泄漏?
我考虑过直接传入带applicationContext的SensorManager:
val sensorManager = applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager SensorOrientationChangeNotifier.getInstance(sensorManager)?.addListener(this)
内容的提问来源于stack exchange,提问作者Taimoor Khan
相关产品推荐
相关产品推荐

