Подтвердить что ты не робот

Как перебросить исключение

В моем 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 по умолчанию.

4b9b3361

Ответ 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), пользователь не увидит диалог сбоя, пока ваш метод не выйдет.