Android应用性能优化
整理自http://androidperformance.com的几篇博客
代码内存优化-Java篇
- 避免创建不必须的对象,虽然GC可以回收不用的对象,但为对象分配内存和回收它们同样是需要消耗资源的。
- 选择
static
而不是Virtual,当我们不需要访问一个对象的值域时,请将方法声明为static,这样方法调用将快15%-20%; - 将常量声明为
static final
类型 - 避免内部的Getters和Setters,在对象的设计中应该有getters和setters,但在类内部访问时,应该直接访问变量;在没有JIT时,直接访问的速度是getters的3倍,有JIT时,是 getters的7倍;
- 使用增强的for循环写法,for(Obj obj:Array); 但如果Array是ArrayList,则使用for(int i=0;i<len;++i)的写法会好一些;
- 使用包级访问,而不是内部类的私有访问,当内部类需要访问外部类的私有域时,请把外部类的私有域声明为包访问权限,但这可能会存在安全问题;
避免使用float,float类型在Android中的访问速度是int型的一半;
Android内存优化——
OnTrimMemory()
优化OnTrimMemory()
回调是Android 4.0开始提供的一个API,它主要是提示开发者在系统内存不足的时候,通过处理部分资源来释放内存,从而避免被系统杀死,进而可以在下一次启动时更快速地启动。这个回调方法主要就是让应用程序在不同情况下对自身占用的内存进行翻译,从而避免被系统杀死,提高用户体验。任何实现了ComponentCallbacks2
接口的类都可以重写实现这个回调方法。
尽管系统在内存不足时是按照LRU Cache从低到高的顺序杀进程的,但它同时会考虑杀死那些占用内存高的应用来快速恢复系统的内存。因此如果你的应用占用内存小,就减少了被系统杀死的概率,从而快速地恢复(如果应用没有被杀死,则再次启动时是热启动,否则就是冷启动,速度之差在2到3倍之间),因此在不同的OnTrimMemory()
回调中释放自己的UI资源,可以提供较好的用户体验。
Android系统会根据不同的内存使用情况,调用这个函数,并传入相应的等级:
TRIM_MEMORY_UI_HIDDEN
表示应用的所有UI界面被隐藏了,也就是用户点击Home键或者Back键导致应用的界面不可见,这时应该释放一些资源;TRIM_MEMORY_RUNNING_MODERATE
表示应用程序可以正常运行,并且不会被杀死,但手机内存已经有点低了,系统可能会根据LRU缓存规则来杀死一些进程了。TRIM_MEMORY_RUNNING_LOW
表示应用程序可以正常运行,并且不会被杀死,但此时手机内存已经非常低了,我们应该释放一些不必须的资源来提升系统性能;TRIM_MEMORY_RUNNING_CRITICAL
表示应用程序可以正常运行,但此时系统已经根据LRU缓存规则杀掉大部分缓存进程,这时我们应该尽可以地释放一些不必要的资源,否则系统可能继续杀掉所有缓存中的进程,并且可能杀掉本应该运行的进程,如后台运行的服务;
上面的几个等级是应用程序在运行时会收到的回调,下面的几个等级是应用程序在缓存时,会收到的回调:
TRIM_MEMORY_BACKGROUND
表示手机的内存已经非常低了,系统开始根据据LRU缓存规则来杀死一些进程了,我们的应用处于LRU的最近位置,不太可能被杀掉,但应该去释放一些比较容易恢复的资源,让手机内存更充足,可以让我们的应用在缓存中存活的时间更长;这样当用户返回我们程序时,会感到更顺畅。TRIM_MEMORY_MODERATE
表示手机的内存已经非常低了,系统开始根据LRU缓存规则来杀死一些进程了,我们的应用处于LRU的中间位置,如果手机的内存得不到释放的话,我们的应用程序很大可能会被杀死;TRIM_MEMORY_COMPLETE
表示手机内存已经很低了,系统开始根据LRU缓存规则来杀死一些进程,并且我们的应用处于LRU的最后位置,系统会优先考虑杀死我们的进程,这个时候,应该尽可能释放一切可以释放的资源。
正常情况下,Application
,Activity
,Fragment
,Service
,ContentProvider
都可以实现OnTrimMemory()
回调方法。
在OnTrimMemory回调中应该释放哪些资源
- 缓存,包括图片缓存,文件缓存等,缓存在用户正常使用时很有作用,但当应用程序的UI不可见时,这些缓存就可以清除以减少内存的使用,如第三方图片库的缓存;
- 一些动态生成动态添加的View,这些动态生成动态添加的View且少数情况下才使用到的View,这时候可以释放,下次使用时再动态生成即可。如原生桌面中,会在OnTrimMemory的
TRIM_MEMORY_MODERATE
等级中,释放所有的AppsCustomizePagedView的资源,保证在低内存的时候,桌面应用程序不会被杀掉。
OnTrimMemory()与OnStop()方法区别
OnTrimMemory()
方法中TRIM_MEMORY_UI_HIDDEN
回调只有当我们应用的所有UI不可见时都会触发,但OnStop()
方法会在一个Activity完全不可见时就会调用,如用户打开了我们程序的另一个Activity,因此我们可以在OnStop()
方法中释放一些Activity相关的资源,如取消网络连接,注销广播接收器等,但与UI相关的资源要等到OnTrimMemory()
方法中TRIM_MEMORY_UI_HIDDEN
回调之后才去释放,这样当用户从应用程序的一个Activity跳回到另一个Activity,可以保证程序的响应速度。并且这个回调是在OnStop()
方法之前调用的。
应用场景
- 常驻内存的应用,如Launcher,电话等,在用户使用完退出后需要调用
OnTrimMemory()
来释放用户使用的多余的内存资源,如动态生成的View,图片缓存,Fragment等; - 有后台Service运行的应用,这些应用不是常驻内存的,意味着可以被任务管理器杀掉,但在某些情况下,用户不会去杀,如音乐,下载。当用户退出UI界面后,音乐还在后台播放,此时应该释放掉一些UI资源和Cache;
Android内存优化--资源篇
- Bitmap优化,Android开发中遇到的大部分内存问题归根结底是Bitmap问题,如果Bitmap没有被释放,要么是用户在使用完这个Bitmap时,没有主动释放Bitmap资源,要么就是这个Bitmap资源被引用没有办法被释放。因此我们需要:
- 主动释放Bitmap资源,当这个Bitmap资源不再使用时,建议手动调用
recycle()
方法,释放其Native内存; - 主动释放ImageView的图片资源
- 主动释放ImageView的背景资源
- 尽量少用Png图,多用NinePatch的图,现在手机的分辨率越来越高,图片资源被加载后占用的内存也越来越大,因此要避免使用大的Png图片,改用NinePatch图。
- 使用大图之前,尽量先对其进行压缩
- 查询数据库后,主动关闭游标,如果使用完后,没有关闭游标,且我们的结果集比较小时,需要常时间大量的操作才会复现内存问题,会给测试和问题排查带来困难和风险;
- 构造Adapter时,使用缓存的contentView,以ListView为例,初始化时,ListView会根据屏幕布局实例化一定数量的View对象,并缓存,并ListView向上滚动时,位于最上面的View对象会被回收用来创建新出现的最后的ListView Item,contentView就是那个被缓存起来的View对象。如果每次使用都重新实例化一个View对象,即浪费资源,也浪费时间,会消耗大量的内存资源。
- 及时释放对象的引用,当我们使用完某个对象时,要及时释放掉这个对象的引用,以便当前这个对象在不需要时,可以被GC掉;否则,由于没有及时释放掉对象的引用,导致当前这个对象一直不能被回收,后面需要用到这个对象时,则会重复创建,让系统存在大量的不可回收的对象,最后导致OutOfMemory; 即当我们在对象B中 引用了一个对象A,则B应该在使用完A对象后,及时释放A对象的引用,以便在使用完对象B后,对象B可以被系统回收。
- 在Activity中释放资源
- 消除过度绘制,过度绘制指一个像素被绘制多次,如TextView中含有背景,则TextView的文本像素就会被绘制两次,一次是绘制背景,一次是文本;产生过度绘制的原因有:同一层级的View的叠加和复杂的层级叠加
- 使用系统自带的资源
- 使用内存相关工具检测,在开发的过程中,有意识地使用内存检测工具来进行专门的检查,如Lint,MAT等
Android内存优化——官方篇
- 节制地使用Service,当我们启动一个Service时,系统会倾向于将这个Service依赖的进程保留,这会让这个进程变得非常耗内存,只有当任务需要运行时,才让Service运行起来。因此为了控制Service的生命周期,官方推荐用IntentService替代Service,这样当任务执行完后,这个Service会自动停止,从而最大限度地避免Service内存泄漏。
- 当界面不可见和内存紧张时,释放内存(
OnTrimMemory()
回调) - 检查可以使用的内存数量
- 避免在Bitmap上浪费内存,不要去加载不需要的高分辨率的图片;
- 使用优化过的容器,如
SparseArray
,SparseBooleanArray
,LongSparseArray
- 为序列化数据使用
nano protobufs
; - 避免使用依赖注入框架;
- 使用
ProGuard
来剔除不需要的代码; - 对最终的APK使用
zipalign
; - 分析应用的内存使用情况,进行优化;
Android应用性能优化的更多相关文章
- Android应用性能优化(转)
人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...
- Android客户端性能优化(魅族资深工程师毫无保留奉献)
本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Androi ...
- Android APP 性能优化的一些思考
说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...
- 包建强的培训课程(9):Android App性能优化
v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...
- Android app 性能优化的思考--性能卡顿不好的原因在哪?
说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...
- android app性能优化大汇总
这里根据网络上各位大神已经总结的知识内容做一个大汇总,作为记录,方便后续“温故知新”. 性能指标: (1)使用流畅度: 图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染.高的帧率可以 ...
- Android开发性能优化总结(一)
安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户. 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流. ...
- Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手
图片加载性能优化永远是Android领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco.Picasso.UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降 ...
- (转) Android开发性能优化简介
作者:贺小令 随着技术的发展,智能手机硬件配置越来越高,可是它和现在的PC相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于PC的桌面应用程序.以上理由,足以 ...
- fir.im Weekly - 如何进行 Android App 性能优化
关于 Android App 的优化,@anly-jun 用 3 个月完成了这一系列文章,从 性能分析工具 到 ANR .Layout .消除卡顿 到 内存优化.内存分析工具大概十五六篇,并对此做一个 ...
随机推荐
- jquery selector 基础
转自:http://www.cnblogs.com/zwl12549/archive/2008/08/09/1264163.html query的这套选择符是比较帅气的,借用了XPath2.0和CSS ...
- php发送http请求方法实例及详解
http请求有get,post. php发送http请求有三种方式[我所知道的有三种,有其他的告诉我]. file_get_contents();详情见:http://www.whosmall.com ...
- Get&Post登录
#import "MJViewController.h" @interface MJViewController () @property (weak, nonatomic) IB ...
- ASP.NET程序单客户端(浏览器)登录的实现方案
需求描述:当用户的账户在另一个浏览器中登录的时候,需要把当前浏览器的登录强制下线.这种需求在业务系统,或付费视频服务网站中比较常见. 这种需求我称之为"单客户端(浏览器)"登录,与 ...
- Java关键字——transient
当使用Serializable接口实现序列化操作时,如果一个对象中的某一属性不希望被序列化,则可以使用transient关键字进行声明 import java.io.File; import java ...
- MySQL学习笔记——约束
1.约束是在表上强制执行的数据检验规则,约束主要用于保证数据库的完整性. 2.当表中数据有相互依赖性时,可以保护相关的数据不被删除. 3.大部分数据库支持下面五类完整性约束: - NOT NULL非空 ...
- Android学习笔记——SQLite
该工程的功能是实现关于数据库的操作,即creat.update.insert.query.delete 调试的时候请用模拟器,用真机调试的时候进入cmd-adb shell,再进入cd data/da ...
- clipboard复制剪贴板功能,以及用requirejs时报错---Uncaught ReferenceError: Clipboard is not defined
zeroclipboard是走的flash插件,手机浏览器是不支持的,所以不得不舍弃之,用clipboard,clipboard不需要flash就可以完成复制剪切等功能,而且可以兼容pc,移动端,下面 ...
- WebAPI文件上传与下载
http://www.cnblogs.com/GarsonZhang/p/5511427.html https://github.com/GarsonZhang/FileUpLoadAPI
- [Unity] UGUI研究院之游戏摇杆
最近在做Unity基于UGUI的摇杆,发现了一种非常简单并且巧妙的方法,原文在这里, 不过要FQ!!http://godstamps.blogspot.tw/2015/07/unity-ugui-sc ...