/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.gettingmobile.rest;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;
/**
*
* @author sven.wiegand
*/
public final class RequestHandler {
private final RequestHandlerThread thread;
private final RequestProcessor processor;
private final Handler callbackHandler;
public RequestHandler() {
processor = new RequestProcessor();
callbackHandler = new Handler();
thread = new RequestHandlerThread();
}
public void start() {
synchronized (thread.initEvent) {
thread.start();
try {
thread.initEvent.wait();
} catch (InterruptedException ex) {
Log.e(getClass().getName(), "Failed while waiting for handler thread to start", ex);
}
}
}
public void shutdown() {
thread.shutdown();
}
public <R extends Request<T>, T> void send(R request, RequestCallback<R, T> callback)
throws InterruptedException {
thread.getHandler().post(new AsynchronousRequest<R, T>(request, callback));
}
public void send(Request<?> request) throws InterruptedException {
send(request, null);
}
final class RequestHandlerThread extends HandlerThread {
public final Object initEvent = new Object();
private Handler handler;
public RequestHandlerThread() {
super(RequestHandler.class.getName());
}
public void shutdown() {
final Looper l = getLooper();
if (l != null) {
l.quit();
}
}
@Override
protected void onLooperPrepared() {
synchronized (initEvent) {
handler = new Handler();
initEvent.notifyAll();
}
super.onLooperPrepared();
}
public Handler getHandler() {
return handler;
}
}
final class AsynchronousRequest<R extends Request<T>, T> implements Runnable {
public final R request;
public final RequestCallback<R, T> callback;
public AsynchronousRequest(R request, RequestCallback<R, T> callback) {
this.request = request;
this.callback = callback;
}
@Override
public void run() {
try {
final T result = processor.requestResult(request);
callbackHandler.post(new CallbackEvent<R, T>(this, result, null));
} catch (Exception ex) {
callbackHandler.post(new CallbackEvent<R, T>(this, null, ex));
}
}
}
static final class CallbackEvent<R extends Request<T>, T> implements Runnable {
public final AsynchronousRequest<R, T> request;
public final T result;
public final Throwable error;
public CallbackEvent(AsynchronousRequest<R, T> request, T result, Throwable error) {
this.request = request;
this.result = result;
this.error = error;
}
@Override
public void run() {
request.callback.onRequestProcessed(request.request, result, error);
}
}
}