StrictMode是Android2.3加入的一個工具類檀蹋,用于幫助開發(fā)者發(fā)現(xiàn)代碼中的一些不規(guī)范的問題蛇受。比如網(wǎng)絡(luò)操作,磁盤操作等耗時操作對主線程的影響挑庶。
官網(wǎng)鏈接 https://developer.android.com/reference/android/os/StrictMode.html
1麻削、使用
在Application的衍生類的onCreate()方法中調(diào)用即可劳跃,因為我們只需要在調(diào)試時使用红碑,所以注意在發(fā)行版中屏蔽此段代碼
@Override
public void onCreate() {
if (!AppConfigs.isRelease) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
}
2赶站、StrictMode原理
StrictMode原理很簡單诈茧,其實就是Android源碼在相應(yīng)的代碼段預(yù)留了檢測代碼产喉,比如文件open
@Override
public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
BlockGuard.getThreadPolicy().onReadFromDisk();
if ((mode & O_ACCMODE) != O_RDONLY) {
BlockGuard.getThreadPolicy().onWriteToDisk();
}
return os.open(path, flags, mode);
}
3、常用方法介紹
setThreadPolicy()對當(dāng)前線程應(yīng)用監(jiān)測
detectNetwork() 用于檢查UI線程中是否有網(wǎng)絡(luò)請求操作
detectDiskReads() 和 detectDiskWrites() 磁盤讀寫檢查
noteSlowCall針對執(zhí)行比較耗時的檢查
noteSlowCall針對執(zhí)行比較耗時的檢查敢会,用戶可自定義檢測曾沈,使用示例如下
如果線程操作耗時大于500毫秒需要提示給開發(fā)者,noteSlowCall就可以實現(xiàn)這個功能
public class TaskExecutor {
private static long SLOW_CALL_THRESHOLD = 500;
public void executeTask(Runnable task) {
long startTime = SystemClock.uptimeMillis();
task.run();
long cost = SystemClock.uptimeMillis() - startTime;
if (cost > SLOW_CALL_THRESHOLD) {
StrictMode.noteSlowCall("slowCall cost=" + cost);
}
}
}
執(zhí)行一個耗時2000毫秒的任務(wù)
TaskExecutor executor = new TaskExecutor();
executor.executeTask(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
penaltyDeath()鸥昏,當(dāng)觸發(fā)違規(guī)條件時塞俱,直接Crash掉當(dāng)前應(yīng)用程序。
penaltyDeathOnNetwork()吏垮,當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時障涯,Crash掉當(dāng)前應(yīng)用程序。
penaltyDialog()膳汪,觸發(fā)違規(guī)時像樊,顯示對違規(guī)信息對話框。
penaltyFlashScreen()旅敷,會造成屏幕閃爍生棍,不過一般的設(shè)備可能沒有這個功能。
penaltyDropBox()媳谁,將違規(guī)信息記錄到 dropbox 系統(tǒng)日志目錄中(/data/system/dropbox)涂滴,你可以通過如下命令進(jìn)行插件:
adb shell dumpsys dropbox dataappstrictmode --print
permitCustomSlowCalls()友酱、permitDiskReads ()、permitDiskWrites()柔纵、permitNetwork: 如果你想關(guān)閉某一項檢測缔杉,可以使用對應(yīng)的permit方法。*
如果某些操作是你認(rèn)為沒有問題的搁料,可以手動關(guān)閉對該段代碼的檢測或详,代碼示例如下
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder(old)
.permitDiskWrites()
.build());
//TODO: do things you think is ok
StrictMode.setThreadPolicy(old);
detectAll()表示對當(dāng)前線程所有方法應(yīng)用監(jiān)測
setVmPolicy對虛擬機應(yīng)用監(jiān)測
detectActivityLeaks() 用戶檢查 Activity 的內(nèi)存泄露情況
detectLeakedClosableObjects()用于資源沒有正確關(guān)閉時提醒
detectLeakedSqlLiteObjects() 和detectLeakedClosableObjects()的用法類似,用來檢查SQLite對象是否被正確關(guān)閉
detectLeakedRegistrationObjects() 用來檢查 BroadcastReceiver 或者ServiceConnection 注冊類對象是否被正確釋放
setClassInstanceLimit()設(shè)置某個類的同時處于內(nèi)存中的實例上限郭计,可以協(xié)助檢查內(nèi)存泄露
detectAll()表示應(yīng)用所有監(jiān)測
4霸琴、警告查看方式
penaltyDialog()彈出違規(guī)提示對話框.
penaltyLog() 在Logcat 中打印違規(guī)異常信息
5、其他
在手機的調(diào)試模式中也可以開啟嚴(yán)格模式
6昭伸、注意事項
只在開發(fā)階段啟用StrictMode梧乘,發(fā)布應(yīng)用或者release版本一定要禁用它。
嚴(yán)格模式無法監(jiān)控JNI中的磁盤IO和網(wǎng)絡(luò)請求庐杨。
應(yīng)用中并非需要解決全部的違例情況选调,比如有些IO操作必須在主線程中進(jìn)行。