Android性能优化之OOM篇

Android应用中的OOM(Out of Memory,内存溢出)问题通常发生在应用程序占用的内存超过了设备所能提供的限制。OOM错误可能导致应用程序崩溃。

什么是内存溢出?内存泄漏?

内存溢出 (Out of Memory, OOM)

内存溢出是指程序在运行过程中占用的内存超过了系统分配的限制,导致无法为新对象分配内存,从而引发异常或崩溃。在Android开发中,系统会为每个应用分配一定的内存配额,当应用超出此配额时就会触发OOM错误。

例子:

如果应用程序加载了过多的高分辨率图片,而这些图片占用了超过系统允许的内存,程序就会发生内存溢出,导致崩溃。

常见原因:
  • 加载大图片时未进行压缩。
  • 不合理的内存缓存策略。
  • 无法及时回收对象导致内存被占用。
解决方案:
  • 优化图片加载,使用BitmapFactory.Options压缩图片。
  • 限制缓存的大小,使用LruCache来控制缓存的内存占用。
  • 避免频繁创建大型对象,及时释放不再使用的资源。

内存泄漏 (Memory Leak)

内存泄漏是指程序在运行时,本应被释放的内存由于某些原因没有被及时回收,导致内存不断增加,最终可能引发OOM。即使内存泄漏发生时系统没有立即抛出错误,但如果泄漏持续存在,应用的内存使用会逐渐增大,最终导致OOM或性能下降。

例子:

如果一个Activity对象被一个静态变量持有,该Activity在销毁时不会被垃圾回收器回收,导致内存泄漏。

常见原因:
  • 未及时取消注册的监听器或回调。
  • 静态变量或单例持有ActivityContext对象。
  • HandlerAsyncTask等异步任务未能在Activity销毁时正确处理。
解决方案:
  • 避免静态变量持有ContextActivity对象。
  • 确保在适当的时候注销监听器和回调。
  • 使用WeakReference来持有容易引发泄漏的对象。

总结来说,内存溢出是因为程序使用的内存超过系统限制,而内存泄漏是由于程序没有释放不再需要的内存。内存泄漏往往是导致内存溢出的根本原因之一。

内存泄漏 (Memory Leak) 最后会导致内存溢出 (Out of Memory, OOM)。

OOM错误可能导致应用程序崩溃,常见的场景包括:

1. 内存泄漏

  • 问题:内存泄漏是由于对象的引用未能及时释放,导致系统无法回收这些对象的内存。例如,Activity或Context对象被静态变量或长时间运行的任务持有,导致其不能被垃圾回收器回收。
  • 原因:监听器未解除注册、静态变量或单例持有Context对象。
  • 解决:及时释放不再需要的资源,尤其是Activity和Context的引用。

    示例代码:静态变量持有Activity的引用

    public class MemoryLeakActivity extends AppCompatActivity {
    
        // 静态变量持有Activity引用
        private static MemoryLeakActivity instance;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 将Activity的引用赋值给静态变量,导致内存泄漏
            instance = this;
        }
    }
    

    Activity或Context对象被静态变量或长时间运行的任务持有,这种情况会导致ActivityContext对象无法被回收,造成内存泄漏。

  • 示例代码:注册监听器未解除

    public class MemoryLeakActivity extends AppCompatActivity {
    
        private SensorManager sensorManager;
        private SensorEventListener sensorEventListener;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            sensorEventListener = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    // 响应传感器事件
                }
    
                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {
                    // 响应精度变化
                }
            };
    
            // 注册传感器监听器
            sensorManager.registerListener(sensorEventListener, 
                    sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_NORMAL);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 没有解除注册,导致内存泄漏
        }
    }
    

    传感器监听器sensorEventListenerActivity销毁时未解除注册,继续持有Activity的引用,导致内存无法释放。

    解决代码:释放静态变量和解除监听器注册

    public class MemoryLeakActivity extends AppCompatActivity {
    
        private static MemoryLeakActivity instance;
    
        private SensorManager sensorManager;
        private SensorEventListener sensorEventListener;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            instance = this;  // 静态变量持有
    
            sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            sensorEventListener = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值