This page looks best with JavaScript enabled

Android性能优化

 ·  ☕ 4 min read

Android程序不能无限制的使用设备的内存和CPU。正如经典所说,设备的资源不是给程序员用的,是给用户用的。在编写程序时,应该经常注意内存和CPU的使用。

在Android中,过多的使用内存容易导致OOM,过多的使用CPU容易导致手机卡顿甚至ANR。常见的优化方面有:

  • 布局优化
  • 绘制优化
  • 内存泄漏优化
  • 响应速度优化
  • 列表List优化
  • Bitmap优化
  • 线程优化

布局优化

  • 布局的核心是尽量扁平,不要嵌套。

    • 删除无用的控件和层级
    • 使用性能较高的ViewGroup。能用LinearLayout代替RelativeLayout的就尽量用。但是如果使用LinearLayout会产生嵌套布局,那还是用Relativelayout好,布局嵌套越少越好。
  • 使用include merge ViewStub标签

    • <include>用于复用布局。
    • <merge><include>一起使用,用于剔除多余的ViewGroup。如果当前布局是竖向的LinearLayout,include进来的布局根布局也是竖向的LinearLayout,使用<merge>就能去掉多余的这层布局。
    • <ViewStub>用于按需加载布局。使用 ViewStub 标签引入的布局,默认不会被加载,只有通过 ViewStub 的setVisibility 或者inflater方法加载后,ViewStub 就会被它引入的布局替换掉。

绘制优化

在View的onDraw中要避免执行大量的操作:

  • 不用创建大量的局部变量。onDraw方法会被频繁调用,如果一瞬间产生大量临时对象,不仅占用过多内存,还用于引起GC,从而造成卡顿。
  • 不要做耗时操作,也不能执行千万级循环。每帧的绘制时间不要超过16ms(1000/60fps)。

内存泄漏优化

  • 静态变量引用了Context Activity对象,会造成内存泄漏。
  • 单列模式导致的内存泄漏。单列的生命周期和 Application 的生命周期一致。单列如果引用了Activity,Activity销毁之后,一直到程序结束都不会被回收。造成内存泄漏。
  • 属性动画导致内存泄漏。属性动画如果在Activity结束时没有被cancle,就会导致 Activity 不能被释放,造成内存泄漏。解决方法是,在 Activity 的 onDestroy 中调用 animator.cancel()停止动画。
  • Handler 导致的内存泄漏。在 Activity 中创建的Handler持有Activity的引用。如果当 Activity 结束之后,handler所在的线程还在执行,就会造成 Activity 不能被释放。解决方法是,Handler持有Activity的弱引用(WeakReference)。

响应速度优化

  • 避免在主线程做耗时操作。 Activity 5秒没有响应触摸或键盘输入就会触发ANRBroadcastReceiver 10秒没有执行完操作也会触发ANR
  • 当一个进程发生ANR之后,系统会在data/anr目录下创建一个tracks.txt文件记录原因。可以上传该文件到服务器进而分析ANR原因。

列表优化

  • ListView 采用 ViewHolder 避免在getView中执行耗时操作
  • 通过列表的滑动状态来控制加载任务。比如滑动时,不加载网络图片,不进行异步任务。
  • 可以尝试开启硬件加速,提升滑动质量。

Bitmap优化

  • 边界压缩。通过设置options.inJustDecodeBounds = true;只加载图片边界,获取图片的尺寸等信息。
  • 质量降低。通过修改Bitmap.Config修改解码的颜色空间。
  • 缩放图片。通过修改options.inSampleSize压缩图片尺寸。
  • 使用缓存。使用LurCache在内存中缓存Bitmap,使用DiskLruCache实现磁盘缓存。

线程优化

  • 使用线程池控制线程数量和复用线程

其他优化

  • 常量使用 static final修饰
  • 使用Android的特有数据结构:
    • ArrayMap代替HashMap
    • SpareseArray代替以Integer为key的ArrayList。如ArrayList<Integer,Object>
    • Pair成双成对的数据。
  • 尽量采用静态内部类。可以避免非静态内部类隐式持有外部类的引用,造成内存泄漏。(比如推荐在Activity使用静态内部类的Handler)。
  • 合理使用WeakReferenceSoftReference
Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer