日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Android官方开发文档Training系列课程中文版:如何避免ANR?

發(fā)布時間:2024/7/5 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android官方开发文档Training系列课程中文版:如何避免ANR? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址:http://android.xsoftlab.net/training/articles/perf-anr.html#anr

盡管你寫代碼可能通過了世界上所有的性能測試,但是它還是可能會讓人感覺到卡頓。當(dāng)應(yīng)用卡的不成樣子時,系統(tǒng)會給你彈一個”Application Not Responding”的對話框。

在Android中,系統(tǒng)會對那些長時間沒有響應(yīng)的應(yīng)用采取一些措施:彈出一個對話框告訴用戶APP已經(jīng)停止了響應(yīng),如下圖所示:

正出于這個原因,系統(tǒng)會在APP長時間沒有響應(yīng)的時候?yàn)橛脩籼峁┮粋€退出APP的選項(xiàng)。所以使APP能夠及時響應(yīng)這一點(diǎn)是至關(guān)重要的,這樣系統(tǒng)才不會向用戶顯示ANR對話框。

這節(jié)課我們會學(xué)習(xí)Android系統(tǒng)如何檢測應(yīng)用程序是否是未響應(yīng),以及應(yīng)用程序如何保持響應(yīng)能力的一些改進(jìn)措施。

什么觸發(fā)了ANR?

通常情況下,系統(tǒng)會在應(yīng)用程序不再能夠響應(yīng)用戶的輸入時顯示ANR對話框。比如,如果應(yīng)用阻塞在了UI線程的IO操作上,那么系統(tǒng)就不能夠處理用戶的輸入事件?;蛘邞?yīng)用花費(fèi)了大量的時間在內(nèi)存模型的構(gòu)建上或者是在UI線程中計算了游戲的下一步動作。要記住:
即便是最高效的代碼也需要花費(fèi)時間來運(yùn)行。

任何情況下都不要在UI線程中執(zhí)行耗時操作,而是要將這些工作放在一個單獨(dú)的線程中執(zhí)行。這可以使UI線程保持流暢工作(UI線程負(fù)責(zé)驅(qū)動用戶界面的事件循環(huán))。

在Android中,應(yīng)用程序的響應(yīng)態(tài)由Activity Manager及Window Manager負(fù)責(zé)監(jiān)控。系統(tǒng)會在偵測到以下狀況時顯示ANR對話框:

  • 對輸入事件在5秒內(nèi)沒有作出響應(yīng)。
  • BroadcastReceiver在10秒內(nèi)沒有執(zhí)行完畢。

如何避免ANR?

Android應(yīng)用程序默認(rèn)運(yùn)行在UI線程中。這意味著在UI線程中的任何耗時操作都會引發(fā)ANR問題,因?yàn)檫@會使應(yīng)用程序給不到輸入事件或者意圖廣播處理的機(jī)會。

因此,在UI線程中的每個方法都應(yīng)當(dāng)做盡可能少的工作,尤其是Activity的生命周期回調(diào)函數(shù)。像網(wǎng)絡(luò)或數(shù)據(jù)庫操作,或者大量的計算之類的耗時操作應(yīng)當(dāng)在工作線程中執(zhí)行。

創(chuàng)建用于執(zhí)行耗時操作的線程最便捷的方式莫過于使用AsyncTask了。只需要繼承AsyncTask,然后重寫doInBackground()就可以執(zhí)行了。如果要向用戶展示工作進(jìn)度,你可以使用publishProgress()方法,它會回調(diào)onProgressUpdate()方法(該方法運(yùn)行于UI線程)。
在onProgressUpdate()內(nèi)我們可以更新進(jìn)度條。

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {// Do the long-running work in hereprotected Long doInBackground(URL... urls) {int count = urls.length;long totalSize = 0;for (int i = 0; i < count; i++) {totalSize += Downloader.downloadFile(urls[i]);publishProgress((int) ((i / (float) count) * 100));// Escape early if cancel() is calledif (isCancelled()) break;}return totalSize;}// This is called each time you call publishProgress()protected void onProgressUpdate(Integer... progress) {setProgressPercent(progress[0]);}// This is called when doInBackground() is finishedprotected void onPostExecute(Long result) {showNotification("Downloaded " + result + " bytes");} }

使用execute()方法啟動工作線程:

new DownloadFilesTask().execute(url1, url2, url3);

如果不采用這種方式,我們還有另一種實(shí)現(xiàn)方法:創(chuàng)建自己的Thread或HandlerThread。如果采用這種方法,那么應(yīng)該設(shè)置該線程的優(yōu)先級為”background”:通過Process.setThreadPriority()方法及參數(shù)THREAD_PRIORITY_BACKGROUND設(shè)置。
如果沒有設(shè)置該優(yōu)先級,那么該線程會使應(yīng)用感到變慢,因?yàn)樵摼€程的優(yōu)先級默認(rèn)與UI線程的優(yōu)先級一致,它們會互相搶占CPU資源。

如果實(shí)現(xiàn)了自己的Thread或HandlerThread,那么要確保在等待其它工作線程完成之前UI線程不被阻塞—不要調(diào)用Thread.wait()或Thread.sleep()。如果需要等待其它線程的執(zhí)行結(jié)果,可以為UI線程創(chuàng)建一個Handler。這樣做可以使UI線程還可以對
輸入事件保持響應(yīng)能力。這樣就可以避免5秒內(nèi)無響應(yīng)的ANR對話框出現(xiàn)。

BroadcastReceiver在執(zhí)行時間上有特殊的限制,這意味著在其內(nèi)部的工作一定是輕量級的:比如在后臺做一些保存設(shè)置或者發(fā)送通知的工作。所以與UI線程中執(zhí)行的方法一樣,廣播接收器內(nèi)也應(yīng)當(dāng)杜絕耗時操作的出現(xiàn)。

TIP: 你可以使用StrictMode來發(fā)現(xiàn)UI線程中意外出現(xiàn)的耗時操作。

ANR相關(guān)優(yōu)化

一般來說,100~200毫秒是用戶所能感知到應(yīng)用卡頓的極限。下面列出了一些可以避免應(yīng)用程序ANR的一些點(diǎn),同樣也有助于防止出現(xiàn)卡頓的情況:

  • 如果應(yīng)用需要對用戶輸入做大量的后臺工作,可以顯示一個進(jìn)度表示工作正在進(jìn)行。
  • 對于游戲類的復(fù)雜計算,應(yīng)該將這些工作放在工作線程中執(zhí)行。
  • 如果應(yīng)用在初始化階段需要花費(fèi)一些時間,可以考慮顯示一個閃屏頁面或者盡可能快的顯示主界面:展示加載正在進(jìn)行,并進(jìn)行異步數(shù)據(jù)填充。在這些情況下都應(yīng)當(dāng)表明任務(wù)正在進(jìn)行,以免讓用戶認(rèn)為應(yīng)用已經(jīng)卡死。
  • 使用Systrace或Traceview等性能工具檢查APP的響應(yīng)瓶頸。

總結(jié)

以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:如何避免ANR?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。