Android中内存泄漏的相关因素分析(三)

本文详细探讨了Android中Service的应用场景及其与线程的关系,并强调了合理管理Service生命周期的重要性以防止内存泄漏。同时,深入分析了Bitmap的内存占用问题,提供了有效减少内存消耗的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Service的因素

Service简介

Service作为Android中的四大组件之一,若是Local Service,那么对应的Service是运行在主进程的main线程中的,如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上,所以Service和线程是没有任何关系的。Service的具体用法可参见Service使用相关总结

为什么使用Service?

比方说我们使用Thread,当没有显式的停止Thread或者Thread中的方法没有执行完毕的话,Thread是会一直执行的。Thread所在的Activity销毁之后,那么其中的Thread就没有办法执行。但是实际的需求是Thread要不停的隔一段时间去连接服务器做某种同步的话,没有在相应的Activity中调用start()方法,显然是不行的。因此就需要创建并启动一个Service,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例),因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的

Service因素分析

  • Service执行后台任务时,注意只有当任务正在执行的时候才应该让Service运行起来,当任务执行完之后去停止Service的时候,要小心Service停止失败导致内存泄漏,让一个Service在后台一直保持运行,即使它并不执行任何工作,这是编写Android程序时最糟糕的做法之一
  • 启动一个Service时,系统会倾向于将这个Service所依赖的进程进行保留,这样就会导致这个进程变得非常消耗内存。并且,系统可以在LRU cache当中缓存的进程数量也会减少,导致切换应用程序的时候耗费更多性能。严重的话,甚至有可能会导致崩溃,因为系统在内存非常吃紧的时候可能已无法维护所有正在运行的Service所依赖的进程了
  • 为了能够控制Service的生命周期,Android官方推荐的最佳解决方案就是使用IntentService,这种Service的最大特点就是当后台任务执行结束后会自动停止,从而极大程度上避免了Service内存泄漏的可能性

Bitmap的因素

  • 避免加载不需要的分辨率,在很小的ImageView上显示一张高分辨率的图片不会带来什么视觉上的好处,但是会占用很多的内存,值得注意的是一张图片在解析成一个Bitmap对象的时候所占用的内存并不是这个图片在硬盘中的大小,读取到内存中是按像素点来计算的,比如说这张图片是1500*1000像素的,当使用ARGB_8888颜色类型时,每个像素点占用4个字节,总内存就达到1500*1000*4字节,也就是5.7M这是极大的消耗内存的
  • 及时的回收Bitmap的内存, BitmapFactory中生成Bitmap对象都是通过JNI调用方式实现的,所以加载Bitmao对象到内存以后,是包含两部分内存区域的,一部分是Java部分,一部分是C部分的,这个Bitmap对象是有Java部分分配的,不用的时候系统就会自动回收,但是对应的C部分的内存区域,虚拟机是不能直接回收的,这个只能是调用系统的底层的释放功能,所以就需要recycler()方法来释放C部分的内存
    这里写图片描述
    这里写图片描述
// 先判断是否已经回收
if(bitmap != null && !bitmap.isRecycled()){ 
        // 回收并且置为null
        bitmap.recycle(); 
        bitmap = null; 
} 
System.gc();
  • 捕获异常,避免加载Bitmap的时候出现OutOfMemory异常以后程序崩溃,在实例化Bitmap的时候,要对OutOfMemory异常进行捕获,但是注意其中捕捉的方式,Exception和Error是不同的,详见Exception和Error的相关分析
Bitmap bitmap = null;
try {
    // 实例化Bitmap
    bitmap = BitmapFactory.decodeFile(path);
} catch (OutOfMemoryError e) {
    //注意此处不能是Exception之类的,这样不能捕捉到OutOfMemory
}
if (bitmap == null) {
    // 如果实例化失败 返回默认的Bitmap对象
    return defaultBitmapMap;
}

https://blog.youkuaiyun.com/guolin_blog/article/details/42238627/
https://blog.youkuaiyun.com/arui319/article/details/7953690

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值