Android性能調(diào)優(yōu)利器StrictMode

作為Android開發(fā),日常的開發(fā)工作中或多或少要接觸到性能問題,比如我的Android程序運(yùn)行緩慢卡頓,并且常常出現(xiàn)ANR對(duì)話框等等問題奕扣。既然有性能問題,就需要進(jìn)行性能優(yōu)化掌敬。正所謂工欲善其事惯豆,必先利其器。一個(gè)好的工具奔害,可以幫助我們發(fā)現(xiàn)并定位問題楷兽,進(jìn)而有的放矢進(jìn)行解決。本文主要介紹StrictMode 在Android 應(yīng)用開發(fā)中的應(yīng)用和一些問題华临。

什么是StrictMode

StrictMode意思為嚴(yán)格模式芯杀,是用來檢測(cè)程序中違例情況的開發(fā)者工具。最常用的場(chǎng)景就是檢測(cè)主線程中本地磁盤和網(wǎng)絡(luò)讀寫等耗時(shí)的操作雅潭。

嚴(yán)在哪里

既然叫做嚴(yán)格模式瘪匿,那么又嚴(yán)格在哪些地方呢?
在Android中寻馏,主線程,也就是UI線程核偿,除了負(fù)責(zé)處理UI相關(guān)的操作外诚欠,還可以執(zhí)行文件讀取或者數(shù)據(jù)庫讀寫操作(從Android 4.0 開始,網(wǎng)絡(luò)操作禁止在主線程中執(zhí)行漾岳,否則會(huì)拋出NetworkOnMainThreadException)轰绵。使用嚴(yán)格模式,系統(tǒng)檢測(cè)出主線程違例的情況會(huì)做出相應(yīng)的反應(yīng)尼荆,如日志打印左腔,彈出對(duì)話框亦或者崩潰等。換言之捅儒,嚴(yán)格模式會(huì)將應(yīng)用的違例細(xì)節(jié)暴露給開發(fā)者方便優(yōu)化與改善液样。

具體能檢測(cè)什么

嚴(yán)格模式主要檢測(cè)兩大問題振亮,一個(gè)是線程策略,即TreadPolicy鞭莽,另一個(gè)是VM策略坊秸,即VmPolicy。

ThreadPolicy

線程策略檢測(cè)的內(nèi)容有

  • 自定義的耗時(shí)調(diào)用 使用detectCustomSlowCalls()開啟
  • 磁盤讀取操作 使用detectDiskReads()開啟
  • 磁盤寫入操作 使用detectDiskWrites()開啟
  • 網(wǎng)絡(luò)操作 使用detectNetwork()開啟

VmPolicy

虛擬機(jī)策略檢測(cè)的內(nèi)容有

  • Activity泄露 使用detectActivityLeaks()開啟
  • 未關(guān)閉的Closable對(duì)象泄露 使用detectLeakedClosableObjects()開啟
  • 泄露的Sqlite對(duì)象 使用detectLeakedSqlLiteObjects()開啟
  • 檢測(cè)實(shí)例數(shù)量 使用setClassInstanceLimit()開啟

工作原理

其實(shí)StrictMode實(shí)現(xiàn)原理也比較簡(jiǎn)單澎怒,以IO操作為例褒搔,主要是通過在open,read喷面,write星瘾,close時(shí)進(jìn)行監(jiān)控。libcore.io.BlockGuardOs文件就是監(jiān)控的地方惧辈。以open為例琳状,如下進(jìn)行監(jiān)控

@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);
}

其中onReadFromDisk()方法的實(shí)現(xiàn),代碼位于StrictMode.java中咬像。

public void onReadFromDisk() {
    if ((mPolicyMask & DETECT_DISK_READ) == 0) {
      return;
    }
    if (tooManyViolationsThisLoop()) {
      return;
    }
    BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
    e.fillInStackTrace();
    startHandlingViolationException(e);
}

如何使用

關(guān)于StrictMode如何使用算撮,最重要的就是如何啟用嚴(yán)格模式。

放在哪里

嚴(yán)格模式的開啟可以放在Application或者Activity以及其他組件的onCreate方法县昂。為了更好地分析應(yīng)用中的問題肮柜,建議放在Application的onCreate方法中。

簡(jiǎn)單啟用

以下的代碼啟用全部的ThreadPolicy和VmPolicy違例檢測(cè)

if (IS_DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {  
    StrictMode.setThreadPolicy(new      
    StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());    
    StrictMode.setVmPolicy(new VmPolicy.Builder().detectAll().penaltyLog().build());
}

嚴(yán)格模式需要在debug模式開啟倒彰,不要在release版本中啟用审洞。

同時(shí),嚴(yán)格模式自API 9 開始引入待讳,某些API方法也從 API 11 引入芒澜。使用時(shí)應(yīng)該注意 API 級(jí)別。

如有需要创淡,也可以開啟部分的嚴(yán)格模式痴晦。

查看結(jié)果

嚴(yán)格模式有很多種報(bào)告違例的形式,但是想要分析具體違例情況琳彩,還是需要查看日志誊酌,終端下過濾StrictMode就能得到違例的具體stacktrace信息。

adb logcat | grep StrictMode

解決違例

  • 如果是主線程中出現(xiàn)文件讀寫違例露乏,建議使用工作線程(必要時(shí)結(jié)合Handler)完成碧浊。
  • 如果是對(duì)SharedPreferences寫入操作,在API 9 以上 建議優(yōu)先調(diào)用apply而非commit瘟仿。
  • 如果是存在未關(guān)閉的Closable對(duì)象箱锐,根據(jù)對(duì)應(yīng)的stacktrace進(jìn)行關(guān)閉。
  • 如果是SQLite對(duì)象泄露劳较,根據(jù)對(duì)應(yīng)的stacktrace進(jìn)行釋放驹止。

其他技巧

除了通過日志查看之外浩聋,我們也可以在開發(fā)者選項(xiàng)中開啟嚴(yán)格模式,開啟之后幢哨,如果主線程中有執(zhí)行時(shí)間長的操作赡勘,屏幕則會(huì)閃爍,這是一個(gè)更加直接的方法捞镰。

問題來了

通常情況下StrictMode給出的耗時(shí)相對(duì)實(shí)際情況偏高闸与,并不是真正的耗時(shí)數(shù)據(jù)。

  • 在線上環(huán)境即Release版本不建議開啟嚴(yán)格模式岸售。
  • 嚴(yán)格模式無法監(jiān)控JNI中的磁盤IO和網(wǎng)絡(luò)請(qǐng)求践樱。
  • 應(yīng)用中并非需要解決全部的違例情況,比如有些IO操作必須在主線程中進(jìn)行凸丸。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拷邢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屎慢,更是在濱河造成了極大的恐慌瞭稼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腻惠,死亡現(xiàn)場(chǎng)離奇詭異环肘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)集灌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門悔雹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人欣喧,你說我怎么就攤上這事腌零。” “怎么了唆阿?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵益涧,是天一觀的道長。 經(jīng)常有香客問我驯鳖,道長饰躲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任臼隔,我火速辦了婚禮,結(jié)果婚禮上妄壶,老公的妹妹穿的比我還像新娘摔握。我一直安慰自己,他們只是感情好丁寄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布氨淌。 她就那樣靜靜地躺著泊愧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盛正。 梳的紋絲不亂的頭發(fā)上删咱,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音豪筝,去河邊找鬼痰滋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛续崖,可吹牛的內(nèi)容都是我干的敲街。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼严望,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼多艇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起像吻,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤峻黍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拨匆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姆涩,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年涮雷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了阵面。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洪鸭,死狀恐怖样刷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情览爵,我是刑警寧澤置鼻,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站蜓竹,受9級(jí)特大地震影響箕母,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俱济,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一嘶是、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛛碌,春花似錦聂喇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽克饶。三九已至,卻和暖如春誊辉,著一層夾襖步出監(jiān)牢的瞬間矾湃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國打工堕澄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邀跃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓奈偏,卻偏偏與公主長得像坞嘀,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惊来,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容