StrictMode介紹
最新的Android平臺中(Android 2.3起),新增加了一個新的類,叫StrictMode(android.os.StrictMode)。這個類可以用來幫助開發者改進他們編寫的應用,并且提供了各種的策略,這些策略能隨時檢查和報告開發者開發應用中存在的問題,比如可以監視那些本不應該在主線程中完成的工作或者其他的一些不規范和不好的代碼。

StrictMode有多種不同的策略,每一種策略又有不同的規則,當開發者違背某個規則時,每個策略都有不同的方法去顯示提醒用戶。在本文中,將舉例子說明如何使用在Android 中使用 StrictMode。
StrictMode的策略和規則
目前,有兩大類的策略可供使用,一類是關于常用的監控方面的,另外一類是關于VM虛擬機等方面的策略。常用的監控方面的策略有如下這些:
Disk Reads 磁盤讀
Disk Writes 磁盤寫
Network access 網絡訪問
Custom Slow Code 自定義的運行速度慢的代碼分析
前面三種的意思讀者應該很清楚,就是正如它們的名字所示,分別對磁盤的讀和寫,網絡訪問進行監控。而第四種的自定義慢代碼分析,是僅當訪問調用類的時后才觸發的,可以通過這種方法去監視運行緩慢的代碼。當在主線程中調用時,這些驗證規則就會起作用去檢查你的代碼。比如,當你的應用在下載或者解析大量的數據時,你可以觸發自定義運行速度慢代碼的查詢分析,作用很大。StrictMode可以用于捕捉發生在應用程序主線程中耗時的磁盤、網絡訪問或函數調用,可以幫助開發者使其改進程序,使主線程處理UI和動畫在磁盤讀寫和網絡操作時變得更平滑,避免主線程被阻塞的發生。
而VM方面的策略重點關注如下幾類:
內存泄露的Activity對象
內存泄露的SQLite對象
內存泄露的釋放的對象
其中,內存泄露的Activity對象和內存泄露的SQLite對象都比較好理解,而所謂對關閉對象的檢查,主要是去監視那些本該釋放的對象,比如應該調用close()方法的對象。
當開發者違反某類規則時,每種策略都會有不同的方法令開發者知道當時的情況。相關的違反情況可以記錄在LogCat中或者存儲在DropBox中(android.os.DropBox)服務中。而常用監控類的策略還會在當違規情況發生時顯示相關的對話框和當時的上下文環境,所有的這些都為了能讓開發者盡快地了解程序的瑕疵,以提交程序的質量。下面分步講解如何使用stritctmode。
第一步 啟用strictmode
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDialog() 打印logcat,當然也可以定位到dropbox,通過文件保存相應的log
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
.penaltyLog()
.build());
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
super.onCreate();
當應用啟用了strictmode模式時,其實跟普通的應用沒什么兩樣,在測試和運行時,跟平時運行普通應用程序一樣就可以了。當啟用了Strictmode模式時,會監視所有的程序運行情況,當發現出現重大問題或違背策略規則時,會提示用戶。下面是當運行啟用了strictmode模式的應用時,當發現違背規則時,顯示給用戶的信息,細心觀察下跟普通的出錯信息有什么不同吧。
09-04 16:15:34.592: DEBUG/StrictMode(15883): StrictMode policy violation; ~duration=319 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=31 violation=1 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1041) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:219) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:83) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.database.sqlite.SQLiteDatabase.updateWithOnConflict(SQLiteDatabase.java:1829) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.database.sqlite.SQLiteDatabase.update(SQLiteDatabase.java:1780) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at com.mamlambo.tutorial.tutlist.data.TutListProvider.update(TutListProvider.java:188) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.content.ContentProvider$Transport.update(ContentProvider.java:233) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.content.ContentResolver.update(ContentResolver.java:847) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at com.mamlambo.tutorial.tutlist.data.TutListProvider.markItemRead(TutListProvider.java:229) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at com.mamlambo.tutorial.tutlist.TutListFragment.onListItemClick(TutListFragment.java:99) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.support.v4.app.ListFragment.onItemClick(ListFragment.java:53) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.widget.AdapterView.performItemClick(AdapterView.java:282) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.widget.AbsListView.performItemClick(AbsListView.java:1037) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2449) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.widget.AbsListView.run(AbsListView.java:3073) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.os.Handler.handleCallback(Handler.java:587) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.os.Handler.dispatchMessage(Handler.java:92) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.os.Looper.loop(Looper.java:132) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at android.app.ActivityThread.main(ActivityThread.java:4123) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at java.lang.reflect.Method.invokeNative(Native Method) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at java.lang.reflect.Method.invoke(Method.java:491) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599) 09-04 16:15:34.592: DEBUG/StrictMode(15883): at dalvik.system.NativeStart.main(Native Method
應該說大部分由StrictMode產生的規則警示都應去遵守,但有時也不是所有產生的信息都表明你的程序有錯誤。比如,在應用程序的主線程中去快速讀寫磁盤其實不會對應用的性能產生太大的影響,又或者你在調試程序階段有一些調試的代碼違反了設定的規則,這些都可以忽略掉這些規則。
忽略規則有兩種方法,一種是單純在代碼中把Strictmode的代碼注釋掉,另外一種比較好的方法是,在需要忽略的時候和地方,增加相應的代碼去讓系統停止使用這些規則去檢查,等開發者認為有必要檢查時,再重新應用這些規則,比如:
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)
.permitDiskWrites()
.build());
doCorrectStuffThatWritesToDisk();
StrictMode.setThreadPolicy(old);
這里首先用old來保存了當前的策略規則,然后doCorrectStuffThatWritesToDisk();
這里,執行了一些向磁盤快速讀寫的操作,最后又重新啟用了這些規則。
小結
StrictMode是一個十分有用的類,它可以很方便地應用于檢查Android應用程序的性能和存在的問題。當開啟這個模式后,開發者能很好地檢查應用中存在的潛在問題,更多的請參考Android文檔中的相關API說明。
Android 開發者
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。