欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android性能優(yōu)化之ANR問題定位分析

 更新時間:2022年08月28日 08:38:20   作者:Ghelper  
這篇文章主要介紹了Android性能優(yōu)化之ANR問題定位分析,ANR應(yīng)用程序未響應(yīng),當(dāng)主線程被阻塞時,就會彈出如下彈窗,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可任意參考一下

前言

ANR(Application Not Response)應(yīng)用程序未響應(yīng),當(dāng)主線程被阻塞時,就會彈出如下彈窗

要么關(guān)閉當(dāng)前app,要么就等待,其實(shí)這個時候沒有挽救的措施,選擇等待最終的結(jié)果也是ANR,最終都需要?dú)⒌魬?yīng)用進(jìn)程,我們看下日志,原因是Input dispatching timed out,點(diǎn)擊事件處理超時導(dǎo)致ANR。

2022-08-27 16:11:53.168 2057-2080/system_process E/ActivityManager: ANR in com.lay.image_process (com.lay.image_process/.MainActivity)
    PID: 31848
    Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago.  Wait queue length: 6.  Wait queue head age: 5525.3ms.)

其實(shí)相對于其他的錯誤,ANR比較棘手在于,沒有崩潰日志,定位問題比較困難,而且ANR是必須要解決的問題,這個用戶體驗(yàn)極差,因此本章的核心在于攻堅(jiān)ANR問題。

1 ANR原因總結(jié)

從上面的日志中,我們看到造成ANR的原因是Input dispatching timed out,那么除此之外,還有什么其他的錯誤。

1.1 KeyDispatchTimeout

input事件在5s之內(nèi)沒有處理,產(chǎn)生ANR;這種異常是比較常見的問題,常發(fā)生在點(diǎn)擊事件處理中,logcat的關(guān)鍵字就是Input dispatching timed out

這里需要說明一點(diǎn),Input事件導(dǎo)致ANR跟下面幾種不同的是,看下面的代碼,點(diǎn)擊按鈕5s后,才彈出toast,這種情況下會發(fā)生ANR嗎?

btnSend.setOnClickListener {
    Thread.sleep(5 * 1000)
    ToastUtils.setText(this)
}

我們可以在私下測試一下,其實(shí)是不會的,如果用戶后續(xù)沒有繼續(xù)輸入事件,那么就不會產(chǎn)生ANR

1.2 BroadCastTimeout

class MyBroadCast : BroadcastReceiver(){
    override fun onReceive(context: Context?, intent: Intent?) {
        //TODO 接收廣播
    }
}

我們在使用廣播接收器接收廣播時,需要重寫B(tài)roadcastReceiver的onReceive方法,當(dāng)前方法是在主線程中,如果在10s內(nèi)沒有處理彎沉,就會ANR。

因此,在onReceive方法中不能做耗時操作,如果需要則需要創(chuàng)建新的線程。logcat關(guān)鍵字是 Timeout of broadcast BroadcastRecord

1.3 ServiceTimeout

class MyService : Service(){

    override fun onCreate() {
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onBind(intent: Intent?): IBinder? {
        TODO("Not yet implemented")
    }

}

同樣,在Service中依然不能做耗時操作,如onCreate、onStartCommand、onBind方法中如果超過20s沒有處理完成,就會ANR。

所以如果需要在服務(wù)中執(zhí)行耗時操作,建議使用IntentService,logcat關(guān)鍵字是 Timeout executing service

1.4 ContentProviderTimeout

四大組件最后一個組件,如果ContentProvider在10內(nèi)沒有處理就會導(dǎo)致ANR,這個組件使用很少,暫時先不分析

綜上所述,如果出現(xiàn)ANR,主要原因就是在主線程執(zhí)行了耗時操作,導(dǎo)致UI線程被阻塞發(fā)生ANR;那么在我們的實(shí)際項(xiàng)目中,有哪些操作,可能會導(dǎo)致ANR呢?

1. 主線程進(jìn)行頻繁的IO操作

不知道我們還有多少在使用SP存儲的,其實(shí)它底層就是通過IO讀寫操作文件,如果頻繁地在主線程進(jìn)行SP讀寫可能會造成卡頓或者ANR,之前就有過線上的ANR事故,建議大家都是用MMKV,讀寫速度秒殺SP;

除此之外,主線程進(jìn)行網(wǎng)絡(luò)操作也會導(dǎo)致ANR

2. 多線程爭奪資源導(dǎo)致死鎖3. CPU資源耗盡

等等......

2 ANR問題解決

2.1 線下問題解決

如果在我們實(shí)際的開發(fā)過程中,如果出現(xiàn)ANR,那么很簡單,打開logcat窗口就可以查看,還有一種方式,就是查看trace日志,路徑為 /data/anr/xxx

 打開trace日志,通過這一部分就能猜到具體原因了,就是因?yàn)樵谥骶€程中,響應(yīng)點(diǎn)擊事件時,線程進(jìn)入休眠阻塞

線下出問題對于我們來說永遠(yuǎn)都是最簡單的,難的就是在線上出了問題,用戶隔你十萬八千里,該如何處理?

2.2 線上問題解決

2.2.1 Bugly

可能很多小伙伴的項(xiàng)目中都集成了bugly,確實(shí)bugly是很不錯的線上監(jiān)控組件,像Crash、ANR都能夠檢測到,但是很多時候,日志是不全的,堆棧信息不全就沒法定位問題,bugly可以作為兜底方案,具體的監(jiān)控方案,我們可以自己實(shí)現(xiàn)。

2.2.2 FileObserver

對于線上監(jiān)控,往往有兩種方式,我這邊先講解第一種,通過FileObserver監(jiān)聽某個目錄下文件是否發(fā)生變化,這里不言而喻了,就是/data/anr/xxx,如果當(dāng)前文件夾中的文件發(fā)生變化,那么意味著ANR發(fā)生了,首先我們先了解一個這個類。

@Deprecated
public FileObserver(String path) {
    this(new File(path));
}

/**
 * Equivalent to FileObserver(file, FileObserver.ALL_EVENTS).
 */
public FileObserver(@NonNull File file) {
    this(Arrays.asList(file));
}

/**
 * Equivalent to FileObserver(paths, FileObserver.ALL_EVENTS).
 *
 * @param files The files or directories to monitor
 */
public FileObserver(@NonNull List<File> files) {
    this(files, ALL_EVENTS);
}

我們先看一下其中比較核心的構(gòu)造方法,F(xiàn)ileObserver能夠監(jiān)聽某個路徑下的文件、某個文件或者文件集合的變化,F(xiàn)ileObserver是一個抽象類,那么我們可以實(shí)現(xiàn)它來監(jiān)聽anr目錄文件的變化

@IntDef(flag = true, value = {
        ACCESS,
        MODIFY,
        ATTRIB,
        CLOSE_WRITE,
        CLOSE_NOWRITE,
        OPEN,
        MOVED_FROM,
        MOVED_TO,
        CREATE,
        DELETE,
        DELETE_SELF,
        MOVE_SELF
})

具體的文件狀態(tài)有以上這些,包括ACCESS(當(dāng)前文件被訪問了)、MODIFY(當(dāng)前文件被修改了)、CREATE(當(dāng)前文件被創(chuàng)建了)、DELETE(當(dāng)前文件被刪除了)等等

class ANRFileObserver(
    val anrPath: String
) : FileObserver(anrPath) {


    override fun onEvent(event: Int, path: String?) {
        when(event){
            ACCESS->{

            }
            MODIFY->{
            }
            DELETE->{

            }
            CREATE->{
            }
        }
    }
}

這里主要是檢測這4種狀態(tài),當(dāng)前文件夾下內(nèi)容有修改時,就將全部的trace文件上傳到服務(wù)端進(jìn)行日志查看。

val observer = ANRFileObserver("/data/anr/")
observer.startWatching()

但是這里需要注意的就是,很多高版本的ROM已經(jīng)不支持當(dāng)前文件夾的查看,甚至需要Root,因此此策略暫時不能應(yīng)用,那么除此之外,還可以通過WatchDog來監(jiān)控線程狀態(tài),從而判斷是否發(fā)生ANR。

2.2.3 WatchDog

從字面意思上看,就是看門狗,其實(shí)這個是Android系統(tǒng)中的一種監(jiān)控機(jī)制,當(dāng)SystemServer進(jìn)程啟動,調(diào)用start方法之后,WatchDog也就啟動了run方法

從上面這張圖可以理解WatchDog的原理:首先WatchDog是一個線程,每隔5s發(fā)送一個Message消息到主線程的MessageQueue中,主線程Looper從消息隊(duì)列中取出Message,如果沒有阻塞,那么在5s內(nèi)會執(zhí)行這個Message任務(wù),就沒有ANR;如果超過5s沒有執(zhí)行,那么就有可能出現(xiàn)ANR。

到此這篇關(guān)于Android性能優(yōu)化之ANR問題定位分析的文章就介紹到這了,更多相關(guān)Android ANR 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論