2012-06-27 39 views
13

Trong onCreate của tôi() để thiết lập một handler UncaughtException như sau:Làm thế nào để tái ném một ngoại lệ

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()); 
    } 
}); 

Nó hoạt động OK, nhưng tôi muốn để có được trở lại hành vi mặc định của hệ thống hiển thị force- đóng hộp thoại cho người dùng.

Nếu tôi cố gắng thay thế cuộc gọi KillProcess() bằng một trình biên dịch throw throwable thì tôi cần phải bao quanh nó bằng một lần thử/nắm bắt.

Nếu tôi bao quanh nó với một 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 {    
     } 
    } 
}); 

Trình biên dịch vẫn phàn nàn rằng throw throwable cần phải được bao quanh với một try/catch.

Tôi làm cách nào để ném lại điều đó? Như vậy, ngoại trừ thông tin Log.e() hệ thống hoạt động chính xác như trước: Như tôi chưa bao giờ đặt trình xử lý UncaughtException mặc định.

Trả lời

18

Hãy thử:

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); 
    } 
} 

và sau đó Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

Phỏng theo this câu trả lời.

+1

Xin lỗi, nhưng điều đó dẫn đến luồng vô tận của Ngoại lệ không bắt buộc và hoàn toàn không có hộp thoại cưỡng bức nào. Không phải những gì tôi đang tìm kiếm. –

+0

Tôi đã cập nhật câu trả lời. – Jeshurun

+0

Hoạt động tuyệt vời! Đang chấp nhận +1. –

3

Nếu bạn đặt trình xử lý ngoại lệ chưa xử lý mặc định, bạn sẽ phải sử dụng ngoại lệ trong đó. Điều đó được phản ánh bởi thực tế là uncaughtException không khai báo bất kỳ ngoại lệ nào.

Sẽ không có lý do rõ ràng nào để ném lại. Nó sẽ chỉ được in trong log lần thứ hai và thread sẽ chết anyway. Nếu bạn thực sự muốn điều đó, sau đó chỉ cần bọc throwable trong RuntimeException và tái ném.

+0

Tôi hiểu và đồng ý rằng không có lý do rõ ràng nào để ném lại.Lý do duy nhất tôi xác định rằng trình xử lý UncaughtException mặc định là vì có ** không có lần đăng nhập đầu tiên! **. Vì vậy, nếu hệ thống không in dấu vết ngăn xếp, * I * muốn in nó. Do đó xử lý. Tôi đã rất hài lòng với hành vi mặc định của hệ thống, ngoại trừ khả năng không giải thích được của nó để in một dấu vết ngăn xếp của ngoại lệ chưa được biết từ 'android.net.http.HttpsConnection.openConnection()'. +1. –

+0

Vì vậy, bạn đã in nó trong trình xử lý. Tại sao lại ném? Chủ đề đã chết ... –

2

Không có lý do gì để tính lại khoản Throwable, theo javadoc, it is simply ignored. Chủ đề chấm dứt tại thời điểm này, bạn chỉ cần thiết lập bất kỳ hành động cuối cùng nào cần thực hiện trước khi thoát.

Vì lợi ích của đối số, nếu bạn đã muốn rethrow một Throwable, bạn muốn làm điều gì đó như thế này:

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. Tôi thậm chí sẽ không thử tái ném vì tôi đồng ý với tuyên bố của bạn (xem [bình luận của tôi] (http://stackoverflow.com/questions/11235513/how-to-re-throw-an-exception#comment14761745_11235599) tới @AlexGitelman). Tuy nhiên, nó sẽ được tốt đẹp để hiển thị hộp thoại gần gũi lực lượng quen thuộc cho người dùng. Bất kỳ ý tưởng làm thế nào để đi về điều này? –

1

đầu tiên, bạn không cần phải rethrow ngoại lệ. uncaughtException() không tiêu thụ ngoại lệ. tuy nhiên bạn phải gọi đến phương thức xử lý ngoại lệ chưa được xử lý mặc định. một cái gì đó như,

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); 
    } 
} 

giây, bạn không cần phải tự mình giết chính mình. UEH mặc định sẽ xử lý khi bạn gọi đến nó.

thứ ba, UEH mặc định sẽ hiển thị (hoặc nguyên nhân được hiển thị) hộp thoại tiêu chuẩn bị lỗi (lực đóng) cho người dùng. hãy nhớ rằng nếu phương thức của bạn bị treo (vì bạn đang làm ví dụ IO), thì người dùng sẽ không thấy hộp thoại sự cố cho đến khi phương thức của bạn thoát.

+0

Tôi thích câu trả lời của bạn nhưng thực tế là nếu tôi nhận xét câu lệnh 'killProcess()' trong phiên bản đầu tiên của trình xử lý của tôi (chỉ để lại câu lệnh 'Log.e()' ở đó, không có hộp thoại đóng chặt nào được hiển thị và quan điểm của ứng dụng chỉ đơn giản là đóng băng cho đến khi tôi buộc đóng ứng dụng theo cách thủ công –

+0

vâng, bạn đã đúng, tôi quên mất một chút về việc gọi UEH mặc định. –

Các vấn đề liên quan