五、ANR產(chǎn)生的原因及其定位分析

ANR 全稱Application Not Responding(應(yīng)用程序無響應(yīng)),一般頁面卡頓時間超過(一般是5秒)一定時間就會出現(xiàn)ANR對話款。Logcat一般會發(fā)現(xiàn)ANR以及traces.txt等字樣。出現(xiàn)ANR主要原因是因為我們在主線程中做了太多耗時操作。

A、ANR產(chǎn)生的原因

只有當(dāng)應(yīng)用程序的UI線程相應(yīng)超時才會引起ANR,超時產(chǎn)生原因一般有兩種
(1)當(dāng)前的事件沒有機(jī)會得到處理,例如UI線程正在響應(yīng)另外一個事件,當(dāng)前事件由于某種原因被阻塞了。
(2)當(dāng)前事件正在處理,但是由于耗時太長沒能及時完成

根據(jù)ANR產(chǎn)生的原因不同,超時事件也不盡相同,從本質(zhì)上講,產(chǎn)生ANR的原因有三種,大致可以對應(yīng)到Android 中四大組件中的三個(activity/view,BroadcastReceiver和service)。

(1)KeyDispatchTimeOut類型

最常見的一種類型,原因是View的按鍵事件或觸摸事件在特定的事件(5秒)內(nèi)無法得到響應(yīng)

(2)BroadcastTimeOut類型

原因是BroadcastReciver的onReceive()函數(shù)運行在了主線程中,在特定的事件(10秒)內(nèi)無法完成處理

(3)ServiceTimeOut類型

比較少出現(xiàn)的一種類型,原因是Service的各個生命周期函數(shù)在特定時間(20秒)內(nèi)無法完成處理

B、典型的ANR問題場景

(1)場景一:

應(yīng)用程序UI線程存在耗時操作,例如在UI線程中進(jìn)行網(wǎng)絡(luò)請求,數(shù)據(jù)庫操作或者文件操作等,可能會導(dǎo)致UI線程無法及時處理用戶輸入等。當(dāng)然在Android4.0之后,如果在UI線程中進(jìn)行網(wǎng)絡(luò)操作,將會拋出NetworkOnMainTreadException異常。

(2)場景二:

應(yīng)用程序的UI線程等待子線程釋放某個鎖,從而無法處理用戶的輸入。

(3)場景三:

耗時的動畫需要大象的計算工作,可能會導(dǎo)致CPU負(fù)載過重

C、ANR的定位和分析

當(dāng)發(fā)生ANR時,可以通過結(jié)合Logcat日志和生成的位于手機(jī)內(nèi)部存儲的/data/anr/traces.txt文件進(jìn)行分析和定位。

(1)Logcat日志信息

查看日志

(2)traces.txt日志信息

有助于問題已定位的信息主要內(nèi)容

a、發(fā)生ANR的進(jìn)程名稱、ID,以及時間。

b、其他

QQ圖片20180921175250.png

c、主工程基本信息

QQ圖片20180921175347.png

d、主線程的詳細(xì)信息

QQ圖片20180921175423.png

e、線程的調(diào)度信息

QQ圖片20180921175502.png

f、線程的上下文信息

QQ圖片20180921175543.png

g、線程的堆棧信息

QQ圖片20180921175624.png

D、ANR的避免和檢測

(1)不要在主線程中做耗時操作

為了避免開發(fā)中可能發(fā)生的ANR的問題,除了切記不要再主線程中做耗時操作,我們也可以借助一些工具來進(jìn)行檢測,從而更有效的避免ANR的引入

(2)StrictMode(代碼檢測)

嚴(yán)格模式StrictMode 是Android SDK提供的一個用來檢測代碼是否存在違規(guī)操作的工具類,StrictMode 主要檢測兩大類為題

a、線程策略ThreadPolicy

檢測可能存在的主線程耗時操作,解決這些檢測到的問題能夠減少應(yīng)用發(fā)生的ANR的概率。需要注意的是我們只能在DEbug版本中使用它,發(fā)布到市場版本必須關(guān)掉。


QQ圖片20180921175750.png

b、虛擬機(jī)策略VmPolicy
QQ圖片20180921175827.png

c、StrictMode使用

使用很簡單,我們只需要在應(yīng)用初始化的地方例如Application或者M(jìn)ainActivity類中onCreate方法中執(zhí)行如下代碼

@Override
protected void onCreate(Bundle savedInstanceState) {
    if (BuildConfig.DEBUG) {
        /**開啟線程模式*/
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
        /**開啟虛擬機(jī)模式*/
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
    }
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_anr);
}

調(diào)用detectAll表示檢測所有的檢測策略,我們也可以根據(jù)應(yīng)用需求只開啟一些策略

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onCreate(Bundle savedInstanceState) {
if (BuildConfig.DEBUG) {
    /**開啟線程模式,某些策略*/
    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            .detectDiskReads()
            .detectDiskWrites()
            .detectCustomSlowCalls()
            .penaltyLog()
            .build());

    /**開啟虛擬機(jī)模式,某些策略*/
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
            .detectActivityLeaks()
            .detectLeakedRegistrationObjects()
            .penaltyLog()
            .build());
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_anr);
}

BlockCanary(非侵入式性能監(jiān)控函數(shù)庫)

BlockCanary是一個非侵入時的性能監(jiān)控函數(shù)庫,他的用法和LeakCanary類似,只不過LeakCanary檢測內(nèi)存泄漏,而BlockCanary主要用來監(jiān)控應(yīng)用主線程的卡頓,它的基本原理利用主線程的消息隊列處理機(jī)制,通過對比消息分發(fā)開始和結(jié)束的事件點來判斷是否超過設(shè)定的時間,如果是,則判斷為主線程卡頓。
集成順序:

a、build.gradle添加依賴

//主線程卡頓監(jiān)控依賴
implementation 'com.github.moduth:blockcanary-android:1.5.0'
//如果僅在debug 包啟用BlockCanary 進(jìn)行卡頓監(jiān)控和提示的話,這樣寫
//debugCompile 'com.github.moduth:blockcanary-android:1.5.0'
//releaseCompile 'com.github.moduth:blockcanary-no-op:1.5.0'

b、在Application中調(diào)用

@Override
public void onCreate() {
super.onCreate();
/**初始化調(diào)用*/
BlockCanary.install(this,new AppBlockCanaryContext()).start();
}

public class AppBlockCanaryContext extends BlockCanaryContext{
/**
 * 實現(xiàn)各種上下文,包括應(yīng)用標(biāo)識符、用戶uid、網(wǎng)絡(luò)類型、卡曼判斷閾值、Log保存位置等
 */
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容