UI线程如果被阻塞5秒的话,那么应用程序此时就会弹出ANR的对话框,ANR对应用程序来说是一个很严重的问题。 如何防止应用程序出现ANR,怎么分析查看导致ANR问题的原因? 我们来介绍Android的严格模式。
怎样开启严格模式
有两种开启方式。
- 开发者选项
进入开发者选项,里面找到启用严格模式,打开。 当应用主线程执行长时间操作的话会闪锁屏幕。
- StrictMode API(代码调用)
可以在Activity或者自定义的Application类的onCreate方法里面开启StrictMode。
// 设置线程策略StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() // 磁盘读 .detectDiskWrites() // 磁盘写 .detectNetwork() // 网络 .penaltyLog() .build());// 设置VM策略StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectActivityLeaks() .detectLeakedSqlLiteObjects() // SQLite 对象 .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() // 触发违规操作,kill应用 .build());
怎样使用StrictMode API
StrictMode可以理解为设置策略、侦测违规操作、惩罚。
设置策略有两种
- setThreadPolicy // 设置线程策略
- setVmPolicy // 设置VM策略
侦测违规操作包含如下,可分为线程策略可侦测的违规操作和 VM策略可侦测的违规操作
线程策略可侦测的违规操作
- detectDiskReads()
- detectDiskWrites()
- detectNetwork()
- detectCustomSlowCalls()
VM策略可侦测的违规操作
- detectActivityLeaks()
- detectLeakedSqlLiteObjects()
- detectLeakedClosableObjects()
- detectFileUriExposure()
- detectLeakedRegistrationObjects()
惩罚方式
- penaltyLog() // 打印log
- penaltyDeath() // 杀掉进程
- penaltyDialog() // 弹出对话框
怎样分析StrictMode Log
可以通过 adb shell 来过滤StrictMode log。
adb logcat -s StrictMode
过滤StrictMode log如下:
02-12 21:43:41.580: E/StrictMode(14269): class com.test.TestActivity; instances=2; limit=102-12 21:43:41.580: E/StrictMode(14269): android.os.StrictMode$InstanceCountViolation: class com.example.testa.BActivity; instances=2; limit=102-12 21:43:41.580: E/StrictMode(14269): at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
instances=2 limit=1,说名限制的TestActivity实例只能是一个,却有两个实例,说明TestActivity有内存泄漏。
其他StrictMode Log 可以根据上下文的描述分析是什么违规导致。