2014-02-18 50 views
1

我有一個處理程序(線程),我發佈Runnables。如果Runnable錯誤地引發RuntimeException,則整個應用程序進程崩潰。作爲默認聽起來合理,但我想趕上這樣的運行時異常,記錄一個錯誤,並繼續運行。不過,我很難完成這項工作。我認爲以下選項:在運行時異常的情況下避免崩潰處理程序線程?

  1. 子類Looper並重寫loop()其中包含調用發佈的Runnable的run()方法的代碼。這是因爲Looper是最終的。
  2. 子類HandlerThread並覆蓋調用Looper.loop()的運行方法。如果發生運行時異常,請再次調用super.run()等等。這是行不通的,因爲「每個線程只能創建一個Looper」。
  3. 在每個可運行類中,包含運行時異常的try-catch。這會起作用,但相當煩人,因爲我有很多不同的Runnable類。另外,如果可誤運行忘記包含try-catch,則不會保護處理程序線程。

在完美的世界裏,Looper會有一個名爲registerExceptionHandler(ExceptionHandler)的成員方法,然後在異常情況下調用ExceptionHandler

任何人都有更好的建議?

+0

把可運行的代碼在try-catch塊,並捕獲異常。所以runnable不會拋出異常。您可以根據需要管理catch塊中的異常。 – guptakvgaurav

+0

對,我認爲這就是我所說的選項3,我認爲這是一種解決方法。問題是我有幾個Runnable類,並希望避免將這些代碼添加到它們中的每一箇中。 – TommyTh

回答

2

試試這個自定義處理程序:

class H extends Handler { 
    public H(Looper looper) { 
     super(looper); 
    } 

    @Override 
    public void dispatchMessage(Message msg) { 
     // catch any Exception 
     try { 
      super.dispatchMessage(msg); 
     } catch (Exception e) { 
      Log.d(TAG, "dispatchMessage " + e.getMessage()); 
     } 
    } 
} 

測試代碼:

HandlerThread ht = new HandlerThread("hthread"); 
ht.start(); 
Handler h = new H(ht.getLooper()); 

Runnable r = new Runnable() { 
    @Override 
    public void run() { 
     throw new RuntimeException("testing exception"); 
    } 
}; 
h.post(r); 
h.post(r); 
+0

是的,這就是你如何設置和啓動HandlerThread。如果你做了'ht.post(new RuntimeGeneratingRunnable)',應用程序進程就會崩潰。任何想法如何避免這一點? – TommyTh

+0

不使用Runnables,使用發送*消息*和Handler.Callback – pskink

+0

正確的,這將工作。我將不得不轉換爲使用消息而不是Runnables,所以我認爲我更願意爲所有Runnables添加try-catch ...如果沒有更好的答案。 – TommyTh

0

在一個完美的世界DefaultExceptionHandler整個應用程序的工作就像一個魅力對我來說。它引起未處理的異常它會觸發。圖書館Android-Remote-StackTrace。你只需要在Application類中註冊這些DefaultHandlerException類的廣播。

段:

public class Portfolio extends Application { 
static Portfolio portfolio; 
public void onCreate() { 
    super.onCreate(); 
    portfolio = this; 
    ExceptionHandler.register(portfolio);// registering for unhandled Exceptions 
    } 
} 

你可以做各種任務與這些如上傳日誌堆棧跟蹤到您的服務器或應用的崩潰與您的未處理的堆棧跟蹤崩潰報告發送郵件。

+0

不完全是我所要求的,但肯定似乎有用。我的直接想法是,「恢復」處理程序線程爲時已晚,但我不確定。我會調查並通知你。感謝您的迴應! – TommyTh

+0

我已經看過它。我不知道有一個DefaultExceptionHandler存在;肯定有趣,值得一讀。對於這種特殊情況,這意味着隊列中的任何掛起的runnables將會丟失,並且處理程序線程將不得不重新啓動等等。不幸的是,這不是一個很好的選擇:-(。 – TommyTh

0

最簡單的方法似乎是從Runnable的推導:

public abstract class RunnableBase implements Runnable 
{ 
    public final void run() 
    { 
     try { 
      runInternal(); 
     } 
     catch(Exception e) { 
      // handle the exception 
     } 
    } 

    // to be implemented by concrete subclasses 
    protected abstract void runInternal(); 
} 
相關問題