package de.tum.in.tumcampusapp.trace;
import android.os.AsyncTask;
/**
* Copied from android-autostarts:
* http://github.com/miracle2k/android-autostarts
* <p/>
* Android's ASyncTask is very useful, but using a background thread
* can be though in the context of the Activity lifecycle, at least
* if you'd prefer your background task to not restart with an
* orientation change.
* <p/>
* This version of ASyncTask tries to alleviate those pains. The idea
* is that you "retain" an instance of this task on orientation change.
* The task can be "connected" to exactly one or zero objects at any
* time. On orientation change, the old instance disconnects itself,
* then the new one connects.
* <p/>
* The object you connect to typically is something that references
* back to your activity (might be the activity itself), and which your
* task needs to do it's job (for example, where it posts it's results
* to).
* <p/>
* This class ensures that whenever a new object connects while the task
* is still active, the preExecute() handler is run again, and if the
* task finished while no object was connected, the processPostExecute()
* handler is run the next time an activity connects.
* <p/>
* Note "processPostExecute()", which is a replacement for the
* "postExcute()" method of ASyncTask which you should use instead.
* <p/>
* TODO: there is a small chance at race conditions here when checking
* for mWrapped and setting mPostProcessingDone. We should fix those
* by using a lock.
*/
public abstract class ActivityAsyncTask<Q, R, S, T> extends AsyncTask<R, S, T> {
protected volatile Q mWrapped;
private volatile boolean mPostProcessingDone;
private T mResult;
public ActivityAsyncTask(Q initialConnect) {
super();
mPostProcessingDone = false;
connectTo(initialConnect);
}
/**
* Q to the given object, or "null" to disconnect.
* <p/>
* Raises an exception if we are already connected.
*/
public final void connectTo(Q wrappedObject) {
if (mWrapped != null && wrappedObject != null) {
throw new IllegalStateException();
}
mWrapped = wrappedObject;
if (mWrapped != null) {
// Set the task up with the new activity.
if (getStatus() == Status.RUNNING) {
onPreExecute();
}
// If we were unable to do the full post processing because of
// no object being available, do so now.
else if (getStatus() == Status.FINISHED && !mPostProcessingDone) {
mPostProcessingDone = true;
processPostExecute(mResult);
mResult = null; // Be sure to free reference now.
}
}
}
/**
* Return whether post processing has been completed.
*/
public boolean postProcessingDone() {
return mPostProcessingDone;
}
@Override
protected void onPostExecute(T result) {
super.onPostExecute(result);
// We need to make sure we only go on if an activity is
// attached. Since it's possible that, say, an orientation
// change happens while we are running, it can happen that
// there isn't one. If so, processPostExecute() will be
// run the next time one is attached.
if (mWrapped == null) {
// Remember result for the next connect.
mResult = result;
} else {
mPostProcessingDone = true;
processPostExecute(result);
}
}
/**
* You should override this rather than onPostExecute()
* to ensure your handler will be called even if at the
* time of a finish the task is not connected.
*/
protected abstract void processPostExecute(T result);
}