package com.elphin.framework.util.async;
import android.os.Handler;
import android.os.Looper;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.*;
/**
* Created with IntelliJ IDEA. User: elphin Date: 13-6-27 Time: 上午12:42
*/
public abstract class AsyncCommand<T> {
// static class AsyncObservableThreadFactory implements ThreadFactory {
//
// static volatile Thread sRunningThread;
//
// @Override
// public Thread newThread(Runnable r) {
// return sRunningThread = new Thread(r, "AsyncCommand");
// }
// }
// private static final AsyncObservableThreadFactory THREAD_FACTORY = new AsyncObservableThreadFactory();
private static final ExecutorService SERVICE = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 30L,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.CallerRunsPolicy());
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
// private static final Field FIELD;
//
// static {
// try {
// FIELD = Observable.class.getDeclaredField("observers");
// FIELD.setAccessible(true);
// } catch (NoSuchFieldException e) {
// throw new RuntimeException(e);
// }
// }
private final Observable mObservable;
// private List<Observer> mOriObservers;
private long mTimeout;
private CountDownLatch mLatch = new CountDownLatch(1);
private volatile boolean isMonitorRunnableSended;
private volatile boolean isTimeout;
private volatile boolean isInterrupt;
private volatile ObservableState mState;
private volatile Object mResponseData;
private final Callback<T> mCallback;
private volatile T mResult;
public AsyncCommand(Observable observable, Callback<T> action, long timeout) {
if (observable == null) {
throw new NullPointerException();
}
mObservable = observable;
mTimeout = timeout < 0 ? 0 : timeout;
mState = ObservableState.INIT;
mCallback = action;
// mOriObservers = getObservers(observable);
// observable.deleteObservers();
observable.addObserver(mInternalObserver);
}
/**
* 获取数据失败可以调用本方法,会触发{@link Callback#onError(Object)}回调方法。
*
* @param msg
*/
public final void fail(final T msg) {
interrupt();
if (Looper.myLooper() != Looper.getMainLooper()) {
HANDLER.post(new Runnable() {
@Override
public void run() {
mCallback.onError(msg);
}
});
} else {
mCallback.onError(msg);
}
}
public final boolean isTimeout() {
return isTimeout;
}
public final boolean isInterrupt() {
return isInterrupt;
}
public final Object getData() {
return mResponseData;
}
public final void interrupt() {
if (mState.compareTo(ObservableState.AFTER) < 0) {
// if (mState == ObservableState.RUN) {
// AsyncObservableThreadFactory.sRunningThread.interrupt();
// }
isInterrupt = true;
}
}
/**
* 状态图:{@link ObservableState#INIT} -> {@link ObservableState#BEFORE} ->
* {@link ObservableState#RUN} -> {@link ObservableState#AFTER} ->
* {@link Callback#onSuccess(Object)}
*
* @return
*/
public final ObservableState getState() {
return mState;
}
/**
* 启动异步任务
*/
public final void start() {
if (mState != ObservableState.INIT) {
throw new IllegalStateException("AsyncCommand can only start once.");
}
if (isInterrupt) {
SERVICE.submit(mInterruptRunnable);
return;
}
mState = ObservableState.BEFORE;
HANDLER.post(mBeforeRunnable);
}
/**
* 子类覆盖该方法。用于做准备工作,在 UI 线程执行。
*/
protected void before() {
}
/**
* 子类覆盖该方法。用于做后台善后工作,在非 UI 线程执行。
*/
protected T after(Object data) {
return null;
}
/**
* 子类覆盖该方法。用于处理以外中断后的工作,在非 UI 线程执行。
*/
protected void interrupt(boolean isTimeout) {
}
protected boolean internalUpdate(Observable observable, Object data) {
return true;
}
private Observer mInternalObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
if (internalUpdate(observable, data)) {
if (isMonitorRunnableSended && !isInterrupt) {
HANDLER.removeCallbacks(mMonitorRunnable);
}
if (isInterrupt) {
return;
}
mResponseData = data;
mLatch.countDown();
}
}
};
private Runnable mMonitorRunnable = new Runnable() {
@Override
public void run() {
isTimeout = true;
interrupt();
}
};
private Runnable mBeforeRunnable = new Runnable() {
@Override
public void run() {
if (isInterrupt) {
SERVICE.submit(mInterruptRunnable);
return;
}
before();
if (isInterrupt) {
SERVICE.submit(mInterruptRunnable);
return;
}
mState = ObservableState.RUN;
SERVICE.submit(mBackgroundRunnable);
if (mTimeout > 0) {
HANDLER.postDelayed(mMonitorRunnable, mTimeout);
isMonitorRunnableSended = true;
}
}
};
private Runnable mEndRunnable = new Runnable() {
@Override
public void run() {
mCallback.onSuccess(mResult);
}
};
private Runnable mBackgroundRunnable = new Runnable() {
@Override
public void run() {
try {
mLatch.await();
recoverObservers(); // 获取数据成功,恢复监听器
mState = ObservableState.AFTER;
mResult = after(mResponseData);
if (!isInterrupt) {
mState = ObservableState.END;
HANDLER.post(mEndRunnable);
} else {
mInterruptRunnable.run();
}
} catch (InterruptedException e) {
mState = ObservableState.INTERRUPT;
interrupt(isTimeout);
recoverObservers(); // 获取数据失败,恢复监听器
mState = ObservableState.END;
}
}
};
private Runnable mInterruptRunnable = new Runnable() {
@Override
public void run() {
mState = ObservableState.INTERRUPT;
interrupt(isTimeout);
recoverObservers(); // 获取数据失败,恢复监听器
mState = ObservableState.END;
}
};
// private List<Observer> getObservers(Observable observable) {
// try {
// return new ArrayList<Observer>((List<Observer>) FIELD.get(observable));
// } catch (IllegalAccessException e) {
// throw new RuntimeException(e);
// }
// }
/**
* 该方法放到 {@link #interrupt()} 回调之后执行,给用户在 {@link #interrupt()} 中删除 request
* 的机会
*/
private void recoverObservers() {
mObservable.deleteObserver(mInternalObserver);
// mObservable.deleteObservers();
// if (mOriObservers != null) {
// for (Observer observer : mOriObservers) {
// mObservable.addObserver(observer);
// }
// }
}
}