BadIdeaException
BadIdeaException

Reputation: 2124

Exception handling on AsyncQueryHandler

When using Android's AsyncQueryHandler, is there any easy way to handle exceptions thrown from the asynchronous insert or do I need to write my own version of that class?

Upvotes: 2

Views: 580

Answers (1)

BadIdeaException
BadIdeaException

Reputation: 2124

Poking around the AsyncQueryHandler source it became clear that I could extend it to suit my needs without too much pain. Since "AsyncQueryHandler exception handling" doesn't give you much on google or SO I've attached my source below in case anybody else ever finds themselves in the same situation.

Basically what it does is, it extends AsyncQueryHandler's internal worker thread and wraps a call through to that thread's super.handleMessage in a try-catch block, then sends any caught exceptions back to the main thread in a message, where it gets passed into the onError callback. The default onError just re-throws the exception.

/**
 * Thin wrapper around @link {@link AsyncQueryHandler} that provides a callback to be invoked 
 * if the asynchronous operation caused an exception.
 */
public class SturdyAsyncQueryHandler extends AsyncQueryHandler {
    public SturdyAsyncQueryHandler(ContentResolver cr) {
        super(cr);
    }

    /**
     * Thin wrapper around {@link AsyncQueryHandler.WorkerHandler} that catches any <code>RuntimeException</code>
     * thrown and passes them back in a reply message. The exception that occurred is
     * in the <code>result</code> field.
     */
    protected class SturdyWorkerHandler extends AsyncQueryHandler.WorkerHandler {
        public SturdyWorkerHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            try {
                super.handleMessage(msg);
            } catch (RuntimeException x) {
                // Pass the exception back to the calling thread (will be in args.result)
                WorkerArgs args = (WorkerArgs) msg.obj;
                Message reply = args.handler.obtainMessage(msg.what);
                args.result = x;
                reply.obj = args;
                reply.arg1 = msg.arg1;
                reply.sendToTarget();
            }
        }
    }

    @Override
    protected Handler createHandler(Looper looper) {
        return new SturdyWorkerHandler(looper);
    }

    /**
     * Called when a runtime exception occurred during the asynchronous operation. 
     * <p>
     * The default re-throws the exception
     * @param token - The token that was passed into the operation
     * @param cookie - The cookie that was passed into the operation
     * @param error - The <code>RuntimeException</code> that was thrown during 
     * the operation
     */
    public void onError(int token, Object cookie, RuntimeException error) {
        throw error;
    }

    @Override
    public void handleMessage(Message msg) {
        if (msg.obj instanceof WorkerArgs) {
            WorkerArgs args = (WorkerArgs) msg.obj;
            if (args.result instanceof RuntimeException) {
                onError(msg.what, args.cookie, (RuntimeException) args.result);
                return;
            }
        }
        super.handleMessage(msg);
    }
}

Upvotes: 7

Related Questions