Android常见异常与性能优化
1. ANR异常(Application Not Responsing:应用程序无响应的弹框)
(1) 原因:在主线程进行了耗时操作(如:网络IO操作、数据库操作或耗时计算等)
拓展:运行在主线程的操作如下,尽量避免在它们里面进行耗时操作。
- Activity:Activity的所有生命周期回调运行在主线程(当然可在Activity生命周期回调中开启子线程执行耗时操作)
- service:service运行在主线程(当然可在Service中开启子线程执行耗时操作,如封装好的IntentService内有一个工作线程用来处理耗时操作)
- Broadcast:BroadcastReceiver的onReceive()回调运行在主线程
- Handler:主线程中looper的Handler对象的handMessage()和post(runnable)方法运行在主线程
- AsyncTask:AsyncTask回调中除了doInBackground()方法,其他回调(UI更新相关)都运行在主线程
(2) 解决ANR:主线程中避免耗时操作,让子线程执行耗时任务
。可参考异步消息处理机制
- Thread:创建子线程执行耗时操作
- AsyncTask:抽象类AsyncTask派生出子类的doInBackground()方法来中执行耗时操作
- HandlerThread:HandlerThread线程中创建Handler对象,在handleMessage()方法中执行耗时操作
- IntentService:重写IntentService的onHandleIntent()方法执行耗时任务
2. OOM异常(Out Of Memory)
2.1 概念区分
- 内存抖动:短时间内大量对象被创建又马上被GC释放,即频繁GC(垃圾回收)。瞬间产生的对象会严重占用内存区域,内存区域达到阀值时会触发GC回收掉不用的对象,导致刚刚产生的对象又被回收。
- 内存泄漏:进程中的某些对象已经没有被其他地方引用,但是他们却可以直接或间接地引用其他没被回收的对象,导致GC无法产生作用。
- 内存溢出(OOM):android系统会给每个安卓程序分配一定的内存,当程序所使用的内存超过最大值就会造成内存溢出,就是常说的OOM。
有些内存没有被释放从而失去控制,造成程序可使用的内存越来越少,系统运行速度减慢,严重情况下会导致程序崩溃,所以内存溢出是最严重的内存问题,必须解决。
备注
:内存抖动或内存泄漏累积到一定程度都会造成内存溢出。
2.2 OOM原因
原因:当前占用的内存 + 我们申请的内存资源 > Dalvik虚拟机被分配的最大内存,常见于Bitmap大图加载时出现OOM。
备注:android系统会为每个应用程序分配一个独立的工作空间(即Dalvik虚拟机空间),使各个app运行互不影响;android系统为每一个Dalvik虚拟机设定了最大内存限制。
2.3 解决OOM
(1) Bitmap造成的OOM解决(Bitmap优化)
- 大图压缩:根据压缩比(计算inBitmap属性值)获取缩略图
- 图片显示:加载4类图片资源
- 及时释放Bitmap内存:通过recycle()回调方法回收资源
- 捕获异常(Error属性可以捕获到OOM,Exception属性捕获不到)
(2) 其他OOM解决
- ListView(convertView复用 + 图片三级缓存机制LRU)
- 避免在onDraw()方法里执行对象的创建(频繁GC,造成内存抖动,积累到一定程度导致内存溢出)
- 谨慎使用多进程(使用复杂,同时使用不当会造成更多的内存溢出和程序错误,尽量不要使用)
3. Bitmap位图
4. UI卡顿
(1) UI卡顿原理
android系统每隔16ms就会触发一次页面渲染,若渲染成功(16内能完成相关计算),就更够达到每秒60帧(60fps)的流畅效果;若渲染不成功(16内不能完成相关计算:耗时操作、布局复杂、动画等原因),就会丢帧造成UI卡顿。
1秒渲染次数 = 1s/16ms =1000ms/16ms = 62.5次页面渲染。
(2) UI卡顿常见原因
UI卡顿原因 | 分析 | 优化 | 备注 |
---|---|---|---|
UI线程做了轻微的耗时操作
|
严重将导致ANR | 开启子线程做耗时操作 | 异步消息处理框架 |
布局 layout过于复杂 |
无法在16ms内完成渲染 | 布局优化 | - |
布局层叠 | 导致View过渡绘制(某些像素在同一帧时间内被绘制多次) | 布局优化 | View频繁地触发measure(测量)和layout(摆放)方法,导致耗时过多及整个View频繁地重新渲染,从而使CPU或GPU负载过重 |
同一时间动画 执行次数过多 |
导致CPU或GPU负载过重 | 合理地使用动画 | 动画虽效果好,但是更易造成性能要求 |
内存频繁触发GC(垃圾回收) | 导致暂时阻塞渲染操作 | - | - |
代码质量 | 冗余资源及逻辑等导致加载和执行缓慢 | 代码优化 | - |
5. 内存泄漏
6. 内存管理
(1) 内存管理 = 内存分配 + 内存回收
(2) android 进程优先级:前台进程 > 可见进程 > 服务进程 > 后台进程 > 空
备注:系统会先回收优先级低的进程。
7. 冷启动优化
8. 其他优化
(1) 尽量不要用静态变量存储核心数据
(2) 有关sharePreference的安全问题
- 不能跨进程读写
- 不能存储大数据:sharePreference以key\value的形式存储存储数据,存储过大数据易阻塞主线程,造成UI卡顿
(3) 内存对象序列化
(4) 避免在UI线程做繁重操作