版權(quán)聲明:本文為LooperJing原創(chuàng)文章,轉(zhuǎn)載請注明出處!
StrictMode意思為嚴(yán)格模式,是用來檢測程序中違例情況的開發(fā)者工具。使用一般是場景是檢測主線程中本地磁盤和網(wǎng)絡(luò)讀寫等耗時的操作。注意這個StrictMode是在Anroid2.3以后引入的。嚴(yán)格模式主要檢測兩大問題,一個是線程策略,即TreadPolicy,另一個是VM策略,即VmPolicy。
線程策略(ThreadPolicy)檢測的內(nèi)容有
- 1、自定義的耗時調(diào)用 使用detectCustomSlowCalls()開啟
- 2、磁盤讀取操作 使用detectDiskReads()開啟
- 3、磁盤寫入操作 使用detectDiskWrites()開啟
- 4、網(wǎng)絡(luò)操作 使用detectNetwork()開啟
虛擬機(jī)策略(VmPolicy)檢測的內(nèi)容有
- 1、Activity泄露 使用detectActivityLeaks()開啟
- 2、未關(guān)閉的Closable對象泄露 使用detectLeakedClosableObjects()開啟
- 3、泄露的Sqlite對象 使用detectLeakedSqlLiteObjects()開啟
- 4、檢測實例數(shù)量 使用setClassInstanceLimit()開啟
可以看到線程策略主要與異步處理相關(guān),虛擬機(jī)策略主要與內(nèi)存管理相關(guān)。setThreadPolicy()將對當(dāng)前線程應(yīng)用該策略。如果不指定檢測函數(shù),也可以用detectAll()來替代。penaltyLog()表示將警告輸出到LogCat,你也可以使用其他或增加新的懲罰(penalty)函數(shù),例如使用penaltyDeath()的話,一旦StrictMode消息被寫到LogCat后應(yīng)用就會崩潰。另外虛擬機(jī)策略(VmPolicy)不能通過一個對話框提供警告。
在線程策略(ThreadPolicy)檢測的時候,有幾個penalty系列方法。
- 1、penaltyDeath(),當(dāng)觸發(fā)違規(guī)條件時,直接Crash掉當(dāng)前應(yīng)用程序。
- 2、penaltyDeathOnNetwork(),當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時,Crash掉當(dāng)前應(yīng)用程序。
- 3、penaltyDialog(),觸發(fā)違規(guī)時,顯示對違規(guī)信息對話框。
- 4、penaltyFlashScreen(),會造成屏幕閃爍,不過一般的設(shè)備可能沒有這個功能。
如何使用嚴(yán)格模式
嚴(yán)格模式的開啟可以放在Application或者Activity以及其他組件的onCreate方法。為了更好地分析應(yīng)用中的問題,建議放在Application的onCreate方法中。設(shè)置一次就夠了。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()//開啟所有的detectXX系列方法
.penaltyDialog()//彈出違規(guī)提示框
.penaltyLog()//在Logcat中打印違規(guī)日志
.build());
requestDataFromNet();
}
/**
* 請求數(shù)據(jù)
*/
private void requestDataFromNet() {
URL url;
try {
url = new URL("http://www.baidu.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String lines ;
StringBuilder sb = new StringBuilder();
while ((lines = reader.readLine()) != null) {
sb.append(lines);
}
Log.d("response",sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
比如上面代碼運行之后,就會有下面的彈窗出來警告。
看一下logcat的日志,是在主線程中做了訪問網(wǎng)絡(luò)的操作。
12-19 17:28:54.226 2729-2729/? D/StrictMode: StrictMode policy violation; ~duration=44 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=63 violation=4
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1123)
at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)
at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)
at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
at zhangwan.wj.com.myshare.MainActivity.requestDataFromNet(MainActivity.java:35)
at zhangwan.wj.com.myshare.MainActivity.onCreate(MainActivity.java:27)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
上面分析了是異步處理相關(guān)的例子,現(xiàn)在分析一個內(nèi)存管相關(guān)的例子,比如檢測內(nèi)存泄露檢測,用StrickMode怎么搞?
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()//檢測Activity泄露
.penaltyLog()//在Logcat中打印違規(guī)日志
.build());
UserManger instance = UserManger.getInstance(this);
}
}
比如上面的代碼UserManger持有了Activity的引用,當(dāng)反復(fù)進(jìn)入Activity的時候,Activity不能被回收,導(dǎo)致了內(nèi)存泄露,此時看Logcat。
12-20 09:57:07.626 4787-4787/? E/StrictMode: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1
android.os.StrictMode$InstanceCountViolation: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1
at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
明確告訴我們instances=3,說明泄露了3個MainActivity對象
嚴(yán)格模式除了可以檢測Activity的內(nèi)存泄露之外,還能自定義檢測類的對象泄露。這個從從API 11 開始。
public
StrictMode.VmPolicy.Builder setClassInstanceLimit (Class klass, int instanceLimit)
比如,檢測UserManger有沒有泄露,可以這么寫。
StrictMode.setVmPolicy(new VmPolicy.Builder().setClassInstanceLimit(UserManger.class, 1).penaltyLog().build());
在比如detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),資源沒有正確關(guān)閉時回觸發(fā),detectLeakedRegistrationObjects() 用來檢查 BroadcastReceiver 或者 ServiceConnection 注冊類對象是否被正確釋放等。
StrictMode有個更直接的辦法,在部分手機(jī)上,可以在開發(fā)者選項中開啟嚴(yán)格模式,開啟之后,如果主線程中有執(zhí)行時間長的操作,屏幕則會閃爍。OKStrictMode比較簡單,到此結(jié)束!
參考鏈接:
官網(wǎng)文檔:http://developer.android.com/reference/android/os/StrictMode.html
http://blog.csdn.net/meegomeego/article/details/45746721
Please accept mybest wishes for your happiness and success !