整理自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内存优化--资源篇

  1. Bitmap优化,Android开发中遇到的大部分内存问题归根结底是Bitmap问题,如果Bitmap没有被释放,要么是用户在使用完这个Bitmap时,没有主动释放Bitmap资源,要么就是这个Bitmap资源被引用没有办法被释放。因此我们需要:
  • 主动释放Bitmap资源,当这个Bitmap资源不再使用时,建议手动调用recycle()方法,释放其Native内存;
  • 主动释放ImageView的图片资源
  • 主动释放ImageView的背景资源
  • 尽量少用Png图,多用NinePatch的图,现在手机的分辨率越来越高,图片资源被加载后占用的内存也越来越大,因此要避免使用大的Png图片,改用NinePatch图。
  • 使用大图之前,尽量先对其进行压缩
  1. 查询数据库后,主动关闭游标,如果使用完后,没有关闭游标,且我们的结果集比较小时,需要常时间大量的操作才会复现内存问题,会给测试和问题排查带来困难和风险;
  2. 构造Adapter时,使用缓存的contentView,以ListView为例,初始化时,ListView会根据屏幕布局实例化一定数量的View对象,并缓存,并ListView向上滚动时,位于最上面的View对象会被回收用来创建新出现的最后的ListView Item,contentView就是那个被缓存起来的View对象。如果每次使用都重新实例化一个View对象,即浪费资源,也浪费时间,会消耗大量的内存资源。
  3. 及时释放对象的引用,当我们使用完某个对象时,要及时释放掉这个对象的引用,以便当前这个对象在不需要时,可以被GC掉;否则,由于没有及时释放掉对象的引用,导致当前这个对象一直不能被回收,后面需要用到这个对象时,则会重复创建,让系统存在大量的不可回收的对象,最后导致OutOfMemory; 即当我们在对象B中 引用了一个对象A,则B应该在使用完A对象后,及时释放A对象的引用,以便在使用完对象B后,对象B可以被系统回收。
  4. 在Activity中释放资源
  5. 消除过度绘制,过度绘制指一个像素被绘制多次,如TextView中含有背景,则TextView的文本像素就会被绘制两次,一次是绘制背景,一次是文本;产生过度绘制的原因有:同一层级的View的叠加和复杂的层级叠加
  6. 使用系统自带的资源
  7. 使用内存相关工具检测,在开发的过程中,有意识地使用内存检测工具来进行专门的检查,如Lint,MAT等

Android内存优化——官方篇

  • 节制地使用Service,当我们启动一个Service时,系统会倾向于将这个Service依赖的进程保留,这会让这个进程变得非常耗内存,只有当任务需要运行时,才让Service运行起来。因此为了控制Service的生命周期,官方推荐用IntentService替代Service,这样当任务执行完后,这个Service会自动停止,从而最大限度地避免Service内存泄漏。
  • 当界面不可见和内存紧张时,释放内存(OnTrimMemory()回调)
  • 检查可以使用的内存数量
  • 避免在Bitmap上浪费内存,不要去加载不需要的高分辨率的图片;
  • 使用优化过的容器,如SparseArraySparseBooleanArray,LongSparseArray
  • 为序列化数据使用nano protobufs;
  • 避免使用依赖注入框架;
  • 使用ProGuard来剔除不需要的代码;
  • 对最终的APK使用zipalign;
  • 分析应用的内存使用情况,进行优化;

Android应用性能优化的更多相关文章

  1. Android应用性能优化(转)

    人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...

  2. Android客户端性能优化(魅族资深工程师毫无保留奉献)

    本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Androi ...

  3. Android APP 性能优化的一些思考

    说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...

  4. 包建强的培训课程(9):Android App性能优化

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  5. Android app 性能优化的思考--性能卡顿不好的原因在哪?

    说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...

  6. android app性能优化大汇总

    这里根据网络上各位大神已经总结的知识内容做一个大汇总,作为记录,方便后续“温故知新”. 性能指标: (1)使用流畅度:  图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染.高的帧率可以 ...

  7. Android开发性能优化总结(一)

    安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户. 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流. ...

  8. Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手

    图片加载性能优化永远是Android领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco.Picasso.UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降 ...

  9. (转) Android开发性能优化简介

    作者:贺小令 随着技术的发展,智能手机硬件配置越来越高,可是它和现在的PC相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于PC的桌面应用程序.以上理由,足以 ...

  10. fir.im Weekly - 如何进行 Android App 性能优化

    关于 Android App 的优化,@anly-jun 用 3 个月完成了这一系列文章,从 性能分析工具 到 ANR .Layout .消除卡顿 到 内存优化.内存分析工具大概十五六篇,并对此做一个 ...

随机推荐

  1. JS-制作网页特效——选项卡效果(水平,点击)

    //总结:这个样式的思维很重要,以前刚开始做,想的都是,怎么获取到自己点击的是哪一个li,然后给他以对应的div样式.后来发现难点是,怎么找到另外两个没有被点击的li和他们对应的div.把他们的样式去 ...

  2. js017-错误处理与调试

    js017-错误处理与调试 本章内容 理解浏览器报告的错误 处理错误 调试JS代码 17.2 错误处理 17.2.1 try-catch语句 try{ //possible error code }c ...

  3. python处理中文(待补充)

    字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(en ...

  4. PHP_$_SERVER_说明详解

    PHP编程中经常需要用到一些服务器的一些资料,特把$_SERVER的详细参数整理下,方便以后使用. $_SERVER['PHP_SELF'] #当前正在执行 脚本的文件名,与 document roo ...

  5. SMTP邮箱验证错误解决

    开始报错,是因为权限设置问题,谷歌对第三方应用登录默认关闭,需要开通后python才能自动访问邮件 SMTPAuthenticationError: (502, b'5.5.1 Unrecognize ...

  6. JavaWeb学习笔记——Web开发模式:Mode I和Mode II

  7. JavaScript学习笔记——函数

    javascript函数的声明和调用 将完成某一特定功能的代码集合起来,可以重复使用的代码块. 一.函数的声明方式(创建) A.基本语法 function 关键字 function 函数名([参数1] ...

  8. pulltorefresh滚动到底部

    如果用ListView,让它滚动到顶部,一般是这样写的: if (!listView.isStackFromBottom()) { listView.setStackFromBottom(true); ...

  9. IOS: 模型面数控制

    你可以先试试 生成之后在虚拟机上运行一下就知道了 不过关键也看手机的好坏 場景 人物 面數的話越少越好(但要保持模型的完整)  貼圖解析度也不要太大 資料越少越好 //================ ...

  10. Make命令

    Make命令 一.Make的概念 Make这个词,英语的意思是"制作".Make命令直接用了这个意思,就是要做出某个文件.比如,要做出文件a.txt,就可以执行下面的命令. $ m ...