昔日憑借單元測試,嚴格模式,崩潰日志分析三大法寶,
我同其他同事,一起把360手機衛(wèi)士的錯誤率,降到了萬分之三以下。
時至今日仍然未見到比較好的,使用StrictMode的代碼工具類或者教程,
今天拿出來分享一下,給有志提高代碼質量的猿。
為什么需要嚴格模式
有些問題不能被立刻發(fā)現(xiàn),容易造成很多莫名其妙的現(xiàn)象。
或者短期沒有異常現(xiàn)象,影響到了長期的穩(wěn)定。
例如:內測泄露,文件資源不釋放,數(shù)據(jù)庫不關閉等。
為了能夠即時發(fā)現(xiàn)這些錯誤,安卓引入了嚴格模式這個概念。
嚴格模式的含義
嚴格模式是一個開關,開啟之后一些嚴格檢查的代碼會生效。
檢查到問題后會主動崩潰報錯。
嚴格模式的精神
盡快暴露錯誤,而不是隱藏和繞過錯誤。
嚴格模式有兩個特點:
- 什么時候出錯,什么時候就會報錯;
- 哪里出錯,就會在哪里報錯。
怎樣開啟
嚴格模式是默認關閉等,這樣用戶體驗是穩(wěn)定的,不受影響。
測試過程中,通過開關軟件開啟嚴格模式,這樣能發(fā)現(xiàn)更多問題。
工具類
package ovo.top.app;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.util.Log;
import java.io.File;
/**
* 參考http://www.lxweimin.com/p/98f348fc7688
* Created by 曹建峰(windcao@hotmail.com) on 2017/2/22.
* 單獨控制activity開關
*/
public class StrictModeManager {
private static final String STRICT_MODE_CFG = "ovo.top.stictmode.cfg/enable";
private static final String ACTIVITY_LEAKS_DETECT_CFG = "ovo.top.stictmode.cfg/enable/activity_leaks_detect";
private static final boolean DEBUG = false;
private static boolean sIsInStrictMode = false;
private static boolean sEnableActivityLeaksDetect = false;
private static boolean sIsFlgChecked = false;
public static void init() {
checkStrictModeCfg();
if (sIsInStrictMode) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
if (sEnableActivityLeaksDetect) {
builder.detectAll();
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
builder.detectLeakedClosableObjects();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.detectLeakedRegistrationObjects();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
builder.detectFileUriExposure();
}
}
}
builder.detectLeakedSqlLiteObjects();
}
builder.penaltyLog().penaltyDropBox().penaltyDeath();
StrictMode.setVmPolicy(builder.build());
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectNetwork()
.penaltyLog()
.penaltyDropBox()
.penaltyDialog()
.build());
}
}
public static boolean isInStrictMode() {
checkStrictModeCfg();
return sIsInStrictMode;
}
/**
* 有些情況下我們希望立刻發(fā)現(xiàn)錯誤,有任何異常都曝光出來,而不是帶著錯誤繼續(xù)執(zhí)行。這樣可以盡快發(fā)現(xiàn)錯誤。
* 這種情況下將剛捕獲的異常放到handleException就可以了。
* 嚴格模式下,這些被處理的Exception 仍會立刻拋出。而非嚴格的模式下,會寫日志。
* @param e
* @param msg
*/
public static void handleException(Exception e, String msg) {
if (isInStrictMode()) {
throw new RuntimeException(msg, e);
} else if (DEBUG) {
Log.e("Exception", msg, e);
}
}
private static void checkStrictModeCfg() {
if (sIsFlgChecked == false) {
File strictModeCfgFile = new File(Environment.getExternalStorageDirectory(), STRICT_MODE_CFG);
sIsInStrictMode = strictModeCfgFile.exists();
File activityLeaksCfgFile = new File(Environment.getExternalStorageDirectory(), ACTIVITY_LEAKS_DETECT_CFG);
sEnableActivityLeaksDetect = activityLeaksCfgFile.exists();
sIsFlgChecked = true;
}
}
}
使用方法:
在Application的onCreate中添加一行代碼
public void onCreate() {
StrictModeManager.init();
super.onCreate();
}
開啟開關:
caojianfeng$ adb shell mkdir /sdcard/ovo.top.stictmode.cfg/
caojianfeng$ adb shell mkdir /sdcard/ovo.top.stictmode.cfg/enable
caojianfeng$ adb shell mkdir /sdcard/ovo.top.stictmode.cfg/enable/activity_leaks_detect