I have a piece of code running the background using AsyncTask. The code is similar to this:
private class MyAsyncTask extends AsyncTask<Void, Void, Object> {
public MyAsyncTask() {
// Some init. code
}
@Override
protected Object doInBackground(Void... params) {
// Doing some long running task.
Log.v(TAG, "Finished everything. Returning ...");
return result;
}
@Override
protected void onCancelled(Object result) {
// Either way, run the next one in the line.
Log.v(TAG, "Task cancelled");
}
@Override
protected void onPostExecute(Object result) {
Log.v(TAG, "Task Completed.");
}
}
On Android 4 it works just fine, but when I run it on 2.3 (HTC Wildfire is my only test phone for now), onPostExecute is not called.
I can see the last message from doInBackground, but none of the messages from either onCancelled or onPostExecute. has anyone else faced the same issue? I found this link which talks about a similar problem, but neither gives a clear solution (just suggests using normal thread instead of AsyncTask) nor its precisely what I am looking for.
Any suggestions?
Cheers
Edit 1:
Ok, after spending a day and reading the code for AsyncTask, Handler, and Message in both 2.3 and 4, I have more clues now about what is happening.
First a little bit more about my design. I have a singleton class which is used both in the app and also in some services started from my app. So the AsyncTask code I showed above can be run either from the activity (assuming the singleton is accessed via the activity), or from the service (if the singleton is accessed via service).
Now in API 11+, no matter how the singleton is accessed, the onPostExecute is called just fine. On API 10 and below, if the singleton is accessed from the activity, then onPostExecute is called just fine, but if it's accessed via service, onPostExecute is not called.
Here is more details about where it get stuck. AsyncTask on 2.3 has an FutureTask which overrides done function to send a Message to its internal Handler as follow:
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
Message message;
Result result = null;
try {
result = get();
} catch (final InterruptedException e) {
android.util.Log.w(AsyncTask.LOG_TAG, e);
} catch (final ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (final CancellationException e) {
message = AsyncTask.sHandler.obtainMessage(AsyncTask.MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();
return;
} catch (final Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
message = AsyncTask.sHandler.obtainMessage(AsyncTask.MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();
}
};
The last two lines of the following code calls message.sendToTarget which is supposed to call handleMessage of the Handler class, but it does not! now I have no idea why the callback to the handler happens from an activity and not from a service! I have some solutions how to solve this (simply using AsyncTask class for API15+ in my code at all times), but any explanation about the cause of this would be very much appreciated as I have no knowledge on this!
Thanks