什么是StrictMode
StrictMode即为严苛模式,它可以很方便地应用于检查Android应用程序的性能和存在的问题。当开启这个模式后,开发者能很好地检查应用中存在的潜在问题。最常用的场景就是检测主线程中本地磁盘和网络读写等耗时的操作。
StrictMode的两大策略
1、线程策略,即TreadPolicy
2、VM策略,即VmPolicy。
ThreadPolicy
线程策略检测的主要内容有:
1、detectDiskReads():检测主线程中的磁盘读取操作。
2、detectDiskWrites():检测主线程中的磁盘写入操作。
3、detectNetwork():检测主线程中的联网操作。
4、detectCustomSlowCalls():自定义的耗时调用。
VmPolicy
虚拟机策略检测的主要内容有:
1、detectActivityLeaks():检测Activity泄露。
2、detectLeakedClosableObjects():检测未关闭的Closable对象泄露 。
3、detectLeakedSqlLiteObjects():检测Sqlite对象的泄漏。
4、setClassInstanceLimit():检测某类的实例数量是否超过限制的数量。
上报检测到的问题
如果检测到违例的问题,则用下列的方法上报:
1、penaltyDialog():一检测到违例就弹框提示。
2、penaltyDeath:一检测到违例就应用奔溃。
3、penaltyFlashScreen():一检测到违例就闪烁屏幕。
4、penaltyDeathOnNetwork():一检测到违例就应用崩溃
5、penaltyDropBox():一检测到违例就把日志存到DropBox文件夹中 data/system/dropbox,用adb shell dumpsys dropbox (这里写data/system/dropbox目录下文件的名字) --print查看
6、penaltyLog():一检测到违例就把日志以LogCat的形式打印出来
如何在APP中开启StrictMode
在Application或者Activity以及其他组件的onCreate方法中开启StrictMode,如:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()//线程策略(ThreadPolicy)
.detectDiskReads()//检测在UI线程读磁盘操作
.detectDiskWrites()//检测UI线程写磁盘操作
.detectCustomSlowCalls()//发现UI线程调用的哪些方法执行得比较慢
.detectResourceMismatches()//最低版本为API23 发现资源不匹配
.detectNetwork() //检测在UI线程执行网络操作
.penaltyDialog()//一旦检测到弹出Dialog
.penaltyDeath()//一旦检测到应用就会崩溃
.penaltyFlashScreen()//一旦检测到应用将闪屏退出 有的设备不支持
.penaltyDeathOnNetwork()//一旦检测到应用就会崩溃
.penaltyDropBox()//一旦检测到将信息存到DropBox文件夹中 data/system/dropbox
.penaltyLog()//一旦检测到将信息以LogCat的形式打印出来
.permitDiskReads()//允许UI线程在磁盘上读操作
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()//虚拟机策略(VmPolicy)
.detectActivityLeaks()//最低版本API11 用户检查 Activity 的内存泄露情况
.detectCleartextNetwork()//最低版本为API23 检测明文的网络
.detectFileUriExposure()//最低版本为API18 检测file://或者是content://
.detectLeakedClosableObjects()//最低版本API11 资源没有正确关闭时触发
.detectLeakedRegistrationObjects()//最低版本API16 BroadcastReceiver、ServiceConnection是否被释放
.detectLeakedSqlLiteObjects()//最低版本API9 资源没有正确关闭时回触发
.setClassInstanceLimit(MyClass.class, 2)//设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露
.penaltyLog()//与上面的一致
.penaltyDeath()
.build());
开启检测全部规则
如检测所有的违例问题:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
开启检测部分规则
如只检测在主线程读磁盘的操作,如果检测到则打印到logcat中:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.penaltyLog()
.build());
如检测慢函数:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls()
.penaltyLog()
.build());
showCustomSlowCallFlag();
showCustomSlowCall();
}
private void showCustomSlowCallFlag(){
StrictMode.noteSlowCall("It is Slow Call");
SystemClock.sleep(10000);
}
private void showCustomSlowCall(){
SystemClock.sleep(10000);
}
只有作了标记,才能检测到慢函数并打印log
如检测setClassInstanceLimit:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.setClassInstanceLimit(LimitClass.class, 2)
.penaltyLog()
.penaltyDropBox()
.build());
忽略某些规则
大部分由StrictMode产生的规则警示都应去遵守,但有时也不是所有产生的信息都表明你的程序有错误。比如,在应用程序的主线程中去快速读写磁盘其实不会对应用的性能产生太大的影响,又或者你在调试程序阶段有一些调试的代码违反了设定的规则,这些都可以忽略掉这些规则。如:
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)
.permitDiskWrites()
.build());
doCorrectStuffThatWritesToDisk();
StrictMode.setThreadPolicy(old);
这里首先用old来保存了当前的策略规则,然后doCorrectStuffThatWritesToDisk()。这里,执行了一些向磁盘快速读写的操作,最后又重新启用了这些规则。
注意
1、在线上环境即Release版本不建议开启严格模式。
2、严格模式无法监控JNI中的磁盘IO和网络请求。
3、应用中并非需要解决全部的违例情况,比如有些IO操作必须在主线程中进行。
参考
StrictMode总结
StrictMode检查android开发违反策略的方法
Android性能调优利器StrictMode