ANR 是什么?怎样避免和解决 ANR?
ANR:Application Not Responding,即应用无响应
ANR 一般有三种类型:
1. KeyDispatchTimeout(5 seconds)–主要类型:按键或触摸事件在特定时间内无响应
2. BroadcastTimeout(10 seconds):BroadcastReceiver 在特定时间内无法处理完成
3. ServiceTimeout(20 seconds)–小概率类型:Service 在特定的时间内无法处理完成超时的原因一般有两种:(1)当前的事件没有机会得到处理(UI 线程正在处理前一个事件没有及时完成或者 looper 被某种原因阻塞住)(2)当前的事件正在处理,但没有及时完成。UI 线程尽量只做跟 UI 相关的工作,耗时的工作(数据库操作、I/O、连接网络或者其他可能阻碍 UI 线程的操作)放入单独的线程处理,尽量用 Handler 来处理 UI thread 和 thread 之间的交互。
ANR 的原因
- 耗时的网络访问
- 大量的数据读写
- 数据库操作
- 硬件操作(比如 Camera)
- 调用 thread 的 join()方法、sleep()方法、wait()方法或者等待线程锁的时候
- service binder 的数量达到上限
- system server 中发生 WatchDog ANR
- service 忙导致超时无响应
- 其他线程持有锁,导致主线程等待超时
- 其它线程终止或崩溃导致主线程一直等待
什么是Android 内存泄露
Android 内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到 gc roots 导致无法被 GC 回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。
场景
1. 类的静态变量持有大数据对象:静态变量长期维持到大数据对象的引用,阻止垃圾回收。
2. 非静态内部类的静态实例:非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
3. 资源对象未关闭:资源性对象如 Cursor、File、Socket,应该在使用后及时关闭。未在 finally 中关闭,会导致异常情况下资源对象未被释放的隐患。
4. 注册对象未反注册:未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。
5. Handler 临时性内存泄露:Handler 通过发送 Message 与主线程交互,Message 发出之后是存储在 MessageQueue 中的,有些 Message 也不是马上就被处理的。在 Message 中存在一个 target,是 Handler 的一个引用,如果 Message 在 Queue 中存在的时间越长,就会导致Handler 无法被回收。如果 Handler 是非静态的,则会导致 Activity 或者 Service 不会被回收。
6. 由于 AsyncTask 内部也是 Handler 机制,同样存在内存泄漏的风险。此种内存泄露,一般是临时性的。
7. 多线程相关的匿名内部类和非静态内部类:匿名内部类同样会持有外部类的引用,如果在线程中执行耗时操作就有可能发生内存泄漏,导致外部类无法被回收,直到耗时任务结束,解决办法是在页面退出时结束线程中的任务。
8.Context 导致内存泄漏:禁止声明静态Context变量
9.静态 View 导致内存泄漏
10.WebView 导致的内存泄漏:WebView 只要使用一次,内存就不会被释放,所以 WebView 都存在内存泄漏的问题,通常的解决办法是为 WebView 单开一个进程,使用 AIDL 进行通信,根据业务需求在合适的时机释放掉
网友评论