標籤:
1. 問題描述
閃退(Crash)是用戶端程式在運行時遭遇無法處理的異常或錯誤時而退出應用程式的表現,請從crash發生的原因分類與解決方案、在出現crash後如何捕捉並分析異常這兩個問題給出自己的解決方案。
我們以Android平台為例,介紹下如何捕獲Android應用的閃退資訊,以協助我們定位和解決導致閃退的問題代碼。
2. Android中的閃退
在講解Android中的閃退之前,我們先來簡單的複習下Java中的異常。
(1)Java中的異常
Java中的異常階層如所示:
我們可以看到Throwable類是異常層級中的基類。Error類表示內部錯誤,這類錯誤使我們無法控制的;Exception表示異常,RuntimeException及其子類屬於未檢查異常,這類異常包括ArrayIndexOutOfBoundsException、NullPointerException等,我們應該通過條件判斷等語句避免未檢查異常的發生。IOException及其子類屬於已檢查異常,編譯器會檢查我們是否為所有可能拋出的已檢查異常提供了異常處理器,若沒有則會報錯。對於未檢查異常,我們無需捕獲(當然Java也允許我們捕獲,但我們應該做的事避免未檢查異常的發生)。
瞭解了這些我們大概可以知道,不論Android應用因為什麼原因閃退,我們只要能夠捕獲引起閃退的異常,那麼我們就可以進行異常處理。對於已檢查異常還好說,數量相對較少而且編譯器的強制下能夠保證我們為所有代碼中可能拋出的已檢查異常設定異常處理器。然而對於未檢查異常,我們難以預測代碼在一些極端情形下(比如劣質的SD卡、糟糕的網速)會觸發什麼樣的異常,因而很難捕獲所有可能的未檢查異常。好訊息是Android為我們提供了擷取Android應用的閃退資訊的機制,下面我們就來介紹一下。
(2)捕獲導致閃退的異常
啟動並執行Android進程中存在一個UncaughtExceptionHandler對象(未捕獲異常處理器),我們可以通過Thread類的靜態方法setDefaultUncaughtExceptionHandler設定當前進程的UncaughtExceptionHandler對象。當出現一個未捕獲異常時,系統會調用出現異常的進程的UncaughtExceptionHandler對象的uncaughtException方法,也就是說在Android應用閃退前我們可以在這個方法中擷取引起閃退的異常資訊。UncaughtExceptionHandler是一個介面,其中只定義了一個uncaughtException方法。
基於以上的分析我們知道了:只要將當前進程的未捕獲異常處理器設定為我們自訂的UncaughtExceptionHandler執行個體,我們就可以通過重寫UncaughtExceptionHandler方法來在閃退前擷取導致閃退的異常的詳細資料。下面的代碼中我們的自訂未捕獲異常處理器實現了UncaughtExceptionHandler介面:
public class CrashHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { try { //傳入這個方法的參數e就是引起應用crash的異常,我們可以在這裡擷取異常資訊,可以把異常資訊上傳到伺服器以便統一分析,也可以儲存在檔案系統中 } catch (Exception e) { ... } }}
設計好了自訂未捕獲異常處理器後,我們只需把它設定為當前進程的未捕獲異常處理器即可,相關代碼如下:
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler());
(3)第三方解決方案
關於Android應用的crash分析與處理,有很多成熟的第三方解決方案,比如Bugly、ACRA等,大家如果感興趣可以自行瞭解。
阿里用戶端工程師試題簡析——Android應用的閃退(crash)分析