2012-06-27 41 views
13

W moim onCreate() I ustawić obsługi UncaughtException następująco:Jak ponownie wyjątek

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

To działa OK, ale chciałbym wrócić domyślne zachowanie systemu z wyświetlania Test siły zamknij okno dialogowe dla użytkownika.

Jeśli spróbuję zastąpić wywołanie KillProcess() za pomocą throw throwable, kompilator uskarża się, że muszę otoczyć go metodą prób/catch.

Gdybym otaczają go z 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 {    
     } 
    } 
}); 

Kompilator wciąż narzeka, że ​​throw throwable musi być otoczony try/catch.

Jak mogę ponownie rzucić to, co się da? Taki, że z wyjątkiem tego informacyjnego systemu, system zachowuje się dokładnie tak jak wcześniej: Jak nigdy nie ustawiam domyślnej obsługi UncaughtException.

Odpowiedz

18

Spróbuj:

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

a następnie Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

Adaptacja this odpowiedź.

+1

Przepraszam, ale to skutkuje niekończącym się strumieniem Niewykończonych Wyjątków i w ogóle brakiem dialogu wymuszającego zamknięcie. Nie tego szukam. –

+0

Zaktualizowałem odpowiedź. – Jeshurun

+0

Działa świetnie! Akceptowanie +1. –

3

Jeśli ustawisz domyślny nieobsługiwany moduł obsługi wyjątku, spodziewany jest wyjątek. Znajduje to odzwierciedlenie w tym, że uncaughtException nie zgłasza żadnego wyjątku.

Nie powinno być oczywistych powodów do ponownego rzucenia. Będzie po prostu wydrukowany w dzienniku po raz drugi, a wątek i tak zginie. Jeśli naprawdę tego chcesz, po prostu zawiń w RuntimeException i ponownie rzuć.

+0

Rozumiem i zgadzam się, że nie powinno być żadnego oczywistego powodu, aby ponownie go rzucić.Jedynym powodem, dla którego definiuję domyślną procedurę obsługi UncaughtException, jest ** brak dziennika po raz pierwszy! **. Jeśli więc system nie wydrukuje śladu stosu, * ja * chcę go wydrukować. Stąd opiekun. Byłem bardzo zadowolony z domyślnego zachowania systemu, z wyjątkiem jego niewyjaśnionej niezdolności do wydrukowania śladu stosu tego nieprzekupionego wyjątku z 'android.net.http.HttpsConnection.openConnection()'. +1. –

+0

Więc wydrukowano go w programie obsługi. Po co ponownie rzucać? Wątek jest już martwy ... –

2

Nie ma powodu, aby ponownie rzucać Throwable, jak w przypadku javadoc, it is simply ignored. W tym momencie wątek kończy się, po prostu konfigurujesz ostatnie czynności, które chcesz wykonać przed wyjściem.

Dla argumentu, jeśli chciał rethrow się Throwable, chcesz zrobić coś takiego:

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. Nie zamierzam nawet próbować ponownego rzucania, ponieważ zgadzam się z twoim oświadczeniem (zobacz [mój komentarz] (http://stackoverflow.com/questions/11235513/how-to-re-throw-an-exception#comment14761745_11235599) do @AlexGitelman). Mimo wszystko, byłoby miło wyświetlić to znajome okno dialogowe wymuszające zamknięcie. Masz pomysł, jak sobie z tym poradzić? –

1

pierwsze, nie trzeba do przekaż wyjątek. uncaughtException() nie zużywa wyjątku. jednak musisz wywołać domyślną metodę obsługi wyjątków. więc coś takiego, po drugie, nie trzeba samemu zabijać procesu. domyślny UEH obsłuży to, gdy do niego zadzwonisz.

po trzecie, domyślne UEH pokaże (lub spowoduje wyświetlenie) standardowe okno dialogowe awarii (wymuszenie zamknięcia) dla użytkownika. pamiętaj, że jeśli twoja metoda się zawiesza (ponieważ robisz na przykład IO), to użytkownik nie zobaczy okna awarii, dopóki twoja metoda nie zostanie zakończona.

+0

Uwielbiam twoją odpowiedź, ale w rzeczywistości, jeśli skomentuję instrukcję 'killProcess()' w pierwszej wersji mojego programu obsługi (pozostawiając tylko instrukcję 'Log.e()', nie wyświetla się okno dialogowe wymuszania zamknięcia i widok aplikacji po prostu zawiesza się, aż ręcznie wymuszam zamknięcie aplikacji –

+0

tak, masz rację, zapomniałem o tym, jak wywołać domyślne UEH. –