严苛模式(StrictMode)
??? 眼下有2種策略可用,第一個和線程相關,它主要針對主線程(或UI線程)。因為在主線程中讀寫磁盤和進行網絡訪問都不是好的做法,Google已經在磁盤和網絡代碼中加入了嚴苛模式(StrictMode)鉤子(hook)。假設你對某個線程打開嚴苛模式(StrictMode),當那個線程進行磁盤和網絡訪問,你將獲得警告。你能夠選擇警告方式。一些違例包括用戶慢速調用(custom slow calls 這么翻譯行嗎?),磁盤讀寫,網絡訪問。你能選擇將警告寫入LogCat,顯示一個對話框,閃下屏幕,寫入DropBox日志文件,或讓應用崩潰。最通常的做法是寫入LogCat或讓應用崩潰。列表2-9顯示了一個為線程策略設置嚴苛模式(StrictMode)的樣例。
列表2-9 設置嚴苛模式(StrictMode)的線程策略
view plainprint???? Builder類使得設置變得非常easy,Builder函數定義全部策略都返回Builder對象,從而這些函數能像列表2-9那樣串連在一起。最后調用build()函數返回一個ThreadPolicy對象作為StrictMode對象的setThreadPolicy()函數的參數。注意到setThreadPolicy()是一個靜態函數,因此不須要實例化StrictMode對象。在內部,setThreadPolicy()將對當前線程應用該策略。假設不指定檢測函數,也能夠用detectAll()來替代。penaltyLog()表示將警告輸出到LogCat,你也能夠使用其它或添加新的懲處(penalty)函數,比如使用penaltyDeath()的話,一旦StrictMode消息被寫到LogCat后應用就會崩潰。
??? 你不須要頻繁打開嚴苛模式(StrictMode),你能夠在主活動的onCreate()函數中打開它,你也能夠在Application派生類的OnCreate()函數中設置嚴苛模式(StrictMode)。線程中執行的不論什么代碼都能夠設置嚴苛模式(StrictMode),但你的確僅僅須要設置一次,一次就夠了。
??? 類似于線程策略(ThreadPolicy),嚴苛模式(StrictMode)有虛擬機策略(VmPolicy)。虛擬機策略(VmPolicy)能檢查內存泄漏,譬如,當關閉一個SQLite對象前的完結操作,或其它不論什么類似可關閉對象在關閉前的完結操作。虛擬機策略(VmPolicy)由一個類似的Builder類創建,如列表2-10所看到的。和線程策略(ThreadPolicy)不同的是,虛擬機策略(VmPolicy)不能通過一個對話框提供警告。
列表2-10 設置嚴苛模式(StrictMode)的虛擬機策略
??? 由于設置發生在線程中,嚴苛模式(StrictMode)甚至能在從一個對象到還有一個對象的控制流中找到違例事件。當違例發生,你會驚奇地注意到代碼正執行于主線程,而棧trace將幫助你發現它怎樣發生。于是你能單步調試解決這個問題,或是將代碼移到它自己的后臺線程,或是就保持原來的處理方式。這都取決與你。當然,你可能希望適時關閉嚴苛模式(StrictMode),當你的程序作為產品公布時,你可不希望它僅為了一個警告在你的用戶手里崩潰。
??? 有兩個方法能夠關閉嚴苛模式(StrictMode),最直接的就是移除對應代碼,但這樣做不利于持續開發的產品。你通常能夠定義一個應用級別布爾變量來測試是否須要調用嚴苛模式(StrictMode)代碼。在公布產品前將這個值定義為FALSE。更優雅的方式是利用調試模式(debug mode)的特點,在AndroidManifest.xml中定義這個布爾變量。<application>字段的屬性之中的一個是android:debuggable,其義自明。列表2-11給出了利用該特性的控釋方法。
列表2-11 僅在調試模式設置嚴苛模式(StrictMode)
??? 嚴苛模式(StrictMode)非常不錯,只是在Android 2.3之前的版本號上該模式不工作。為了避免這個問題,你要在StrictMode對象還不存在的時候就驗證版本號是否在Android2.3及以上。你能利用反射技術(reflection),當嚴苛模式(StrictMode)函數有效時間接調用它,反之不去調用。方法非常easy,你能按列表2-12中的代碼處理
列表2-12? 利用反射技術(reflection)調用嚴苛模式(StrictMode)
??? 某些時候你不希望報告全部違例。那在主線程之外的其它線程中設置嚴苛模式(StrictMode)非常不錯。譬如,你須要在正在監視的線程中進行磁盤讀取。此時,你要么不去調用detectDiskReads(),要么在調用detectAll()之后跟一個permitDiskReads()。類似同意函數也適用于其它操作。但要是你要在Anroid2.3之前版本號上做這些事,有辦法嗎?當然有。
??? 當應用中嚴苛模式(StrictMode)無效,假設你試圖訪問它,將拋出一個VerifyError異常。假設你將嚴苛模式(StrictMode)封裝在一個類里,并捕捉這個錯誤,當嚴苛模式(StrictMode)無效時,你能忽略它。列表2-13顯示一個簡單的嚴苛模式(StrictMode)封裝類StrictModeWrapper。列表2-14顯示了怎樣在你的應用中使用這個封裝類。
列表 2–13 在Anroid2.3之前版本號建立嚴苛模式(StrictMode)封裝類
列表 2–14? 在Anroid2.3之前版本號調用嚴苛模式(StrictMode)封裝類
view plainprint?
//假設考慮到關于版本號兼容問題,由于依照上面的寫法在2.3下面系統是沒有問題的,可是在2.3以上的話,就會出錯,所以應該採用下面方式來處理:
@SuppressLint("NewApi")public static void init(Context context) {// check if android:debuggable is set to trueint appFlags = context.getApplicationInfo().flags;if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {try {//Android 2.3及以上調用嚴苛模式Class sMode = Class.forName("android.os.StrictMode");Method enableDefaults = sMode.getMethod("enableDefaults");enableDefaults.invoke(null);} catch (Exception e) {// StrictMode not supported on this device, puntLog.v("StrictMode", "... not supported. Skipping...");}/** StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()* .detectDiskReads() .detectDiskWrites() .detectNetwork()* .penaltyLog() .build()); StrictMode.setVmPolicy(new* StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects()* .penaltyLog() .penaltyDeath() .build());*/}}
總結
以上是生活随笔為你收集整理的严苛模式(StrictMode)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java解析XML获取城市代码
- 下一篇: 从零开始-android 4.2之旅