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)用即可,因?yàn)槲覀冎恍枰谡{(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原理很簡單,其實(shí)就是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就可以實(shí)現(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)閉某一項(xiàng)檢測,可以使用對應(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對虛擬機(jī)應(yīng)用監(jiān)測
detectActivityLeaks() 用戶檢查 Activity 的內(nèi)存泄露情況
detectLeakedClosableObjects()用于資源沒有正確關(guān)閉時提醒
detectLeakedSqlLiteObjects() 和detectLeakedClosableObjects()的用法類似,用來檢查SQLite對象是否被正確關(guān)閉
detectLeakedRegistrationObjects() 用來檢查 BroadcastReceiver 或者ServiceConnection 注冊類對象是否被正確釋放
setClassInstanceLimit()設(shè)置某個類的同時處于內(nèi)存中的實(shí)例上限,可以協(xié)助檢查內(nèi)存泄露
detectAll()表示應(yīng)用所有監(jiān)測
4、警告查看方式
penaltyDialog()彈出違規(guī)提示對話框.
penaltyLog() 在Logcat 中打印違規(guī)異常信息
5、其他
在手機(jī)的調(diào)試模式中也可以開啟嚴(yán)格模式
6、注意事項(xiàng)
只在開發(fā)階段啟用StrictMode,發(fā)布應(yīng)用或者release版本一定要禁用它。
嚴(yán)格模式無法監(jiān)控JNI中的磁盤IO和網(wǎng)絡(luò)請求。
應(yīng)用中并非需要解決全部的違例情況,比如有些IO操作必須在主線程中進(jìn)行。