2012-06-27 98 views
13

在我的onCreate()我設置UncaughtException處理程序如下:如何重新拋出異常

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable throwable) { 
     Log.e(getMethodName(2), "uncaughtException", throwable); 
     android.os.Process.killProcess(android.os.Process.myPid()); 
    } 
}); 

它的工作原理確定,但我想獲得顯示力 - 回系統的默認行爲關閉對話框給用戶。

如果我嘗試用throw throwable替換KillProcess()調用,編譯器會抱怨我需要用try/catch來包圍它。

如果我圍繞着它有一個try/catch:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable throwable) { 
     try { 
      Log.e(getMethodName(2), "uncaughtException", throwable); 
      throw throwable; 
     } 
     catch (Exception e) {   
     } 
     finally {    
     } 
    } 
}); 

編譯器仍然抱怨throw throwable需要用一個try/catch包圍。

如何重新拋出該throwable?除了那些信息量很大的Log.e()之外,系統的行爲與之前完全一樣:因爲我從來沒有設置默認的UncaughtException處理程序。

回答

18

嘗試:

public class CustomExceptionHandler implements UncaughtExceptionHandler { 

    private UncaughtExceptionHandler defaultUEH; 

    public CustomExceptionHandler() { 
     this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); 
    } 

    public void uncaughtException(Thread t, Throwable e) { 
     Log.e("Tag", "uncaughtException", throwable); 
     defaultUEH.uncaughtException(t, e); 
    } 
} 

然後 Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

this答案改編。

+1

對不起,但是這會導致無盡的未捕獲異常流,並且根本沒有強制關閉對話框。不是我在找什麼。 –

+0

我已經更新了答案。 – Jeshurun

+0

工程太棒了!接受+1。 –

3

如果您設置了默認未捕獲的異常處理程序,則需要使用它中的異常。這反映了uncaughtException沒有聲明任何異常的事實。

應該沒有明顯的理由重新拋出它。它只會在第二次日誌中打印出來,線程將無論如何都會死掉。如果你真的想這樣做,那麼只需在RuntimeException包裝扔掉並重新扔掉。

+0

我理解並同意不應該有任何明顯的理由重新拋出它。我定義默認的UncaughtException處理程序的唯一原因是因爲**沒有第一次登錄!**。所以如果系統不打印堆棧跟蹤,*我*要打印它。因此,處理程序。我對系統的默認行爲非常滿意,除了其無法解釋的無法打印來自'android.net.http.HttpsConnection.openConnection()'的未捕獲異常的堆棧跟蹤。 +1。 –

+0

所以你把它印在處理程序中。爲什麼重新投擲?線程已經死了... –

2

沒有理由重新拋出Throwable,按照javadoc, it is simply ignored.線程在此時終止,您只需設置在退出之前要嘗試的最後一個操作。

對於參數的緣故,如果你確實想重新拋出一個拋出,你會做這樣的事情:

public void reThrow(Throwable t) { 
    if (RuntimeException.class.isAssignableFrom(t.getClass())) { 
     throw (RuntimeException)t; 
    } else if (Error.class.isAssignableFrom(t.getClass())) { 
     throw (Error) t; 
    } else { 
     throw new UndeclaredThrowableException(t); 
    } 
} 
+0

+1。我甚至不會嘗試重新投擲,因爲我同意你的說法(請參閱[我的評論](http://stackoverflow.com/questions/11235513/how-to-re-throw-an-exception#comment14761745_11235599)到@AlexGitelman)。儘管如此,將這個熟悉的強制關閉對話框顯示給用戶會很好。任何想法如何去解決這個問題? –

1

首先,你不需要重新拋出異常。 uncaughtException()不消耗異常。但是您必須調用默認的未捕獲的異常處理程序的方法。所以類似,

class MyUEH implements UncaughtExceptionHandler { 
    private static final UncaughtExceptionHandler default = Thread.getDefaultUncaughtExceptionHandler(); 

    public void uncaughtException(Thread t, Throwable e) { 
     Log.e("Tag", "uncaughtException", throwable); 
     default.uncaughtException(t, e); 
    } 
} 

秒,你不需要自己殺死進程。默認的UEH將在您撥打電話時處理該問題。

第三,默認UEH將向用戶顯示(或導致顯示)標準崩潰(強制關閉)對話框。請記住,如果你的方法掛起(因爲你正在做IO),那麼用戶將不會看到崩潰對話框,直到你的方法退出。

+0

我愛你的答案,但現實情況是,如果我在處理程序的第一個版本中註釋掉'killProcess()'語句(只留下'Log.e()'語句,則不會顯示強制關閉對話框,應用程序的視圖只是凍結,直到我手動強制關閉應用程序。 –

+0

是的,你是對的,我忘記了關於調用默認UEH的小知識。 –