在运行时异常的情况下避免崩溃处理程序线程?

时间:2014-02-18 12:49:44

标签: android android-handler

我有一个Handler(Thread),我在其上发布了Runnables。如果Runnable错误地抛出RuntimeException,整个应用程序进程崩溃。作为默认听起来合理,但我想捕获这样的运行时异常,记录错误,并继续运行。但是,我很难做到这一点。我想到了以下几个选项:

  1. 子类Looper并覆盖loop(),其中包含调用已发布的Runnables的run()方法的代码。由于Looper是最终版,因此无效。
  2. 子类HandlerThread并覆盖调用Looper.loop()的run方法。如果出现运行时异常,请再次调用super.run(),依此类推。这不起作用,因为“每个线程只能创建一个Looper”。
  3. 在每个runnable类中,包含Run-exception的try-catch。这会有效,但是因为我有很多不同的Runnable类,所以很烦人。此外,如果错误的runnable忘记包含try-catch,则不会保护处理程序线程。
  4. 在一个完美的世界中,Looper会有一个名为registerExceptionHandler(ExceptionHandler)的成员方法,如果出现异常则会调用ExceptionHandler

    有人有更好的建议吗?

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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
   }
 }

您可以执行各种任务,例如将日志堆栈跟踪上传到您的服务器,或者使用未处理的堆栈跟踪将应用程序崩溃时的邮件发送为崩溃报告。

答案 2 :(得分: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();
}