Как перебросить исключение
В моем 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());
}
});
Он работает нормально, но я хотел бы вернуть системное поведение по умолчанию отображения диалога принудительного закрытия пользователя.
Если я попытаюсь заменить вызов KillProcess()
на throw throwable
, компилятор жалуется, что мне нужно окружить его с помощью 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.
Как я могу перебросить эту возможность? Такой, что кроме этого информативного Log.e()
система ведет себя точно так же, как и раньше: Как я никогда не устанавливал обработчик UncaughtException по умолчанию.
Ответы
Ответ 1
Try:
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());
Адаптировано из этого ответа.
Ответ 2
Если вы устанавливаете обработчик исключенных исключений по умолчанию, вы должны использовать в нем исключение. Это отражается в том, что uncaughtException
не объявляет никаких исключений.
Не должно быть очевидной причины повторного броска. Он будет просто напечатан в журнале второй раз, и нить все равно умрет. Если вы действительно этого хотите, то просто оберните его броском в RuntimeException
и повторите бросок.
Ответ 3
Нет причин для восстановления Throwable, в соответствии с javadoc, он просто игнорируется. Нить заканчивается на этом этапе, вы 'просто устанавливая все последние действия, которые он пытается выполнить перед выходом.
Для аргументации, если вы хотите перебросить бросок, вы сделаете что-то вроде этого:
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);
}
}
Ответ 4
во-первых, вам не нужно повторно выбрасывать исключение. 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), пользователь не увидит диалог сбоя, пока ваш метод не выйдет.