Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AsyncTask Not Updating on UI thread

I have an AsyncTask updating an ActionBarSherlock progress implementation. Somehow the onProgressUpdate is throwing a threading error though it claims to execute on the UI thread.

protected void onProgressUpdate(Integer... values)
{
    setSupportProgress(values[0]);
}

The error is:

03-06 00:13:11.672: E/AndroidRuntime(4183): at com.anthonymandra.framework.GalleryActivity$ShareTask.onProgressUpdate(GalleryActivity.java:476)

Only the original thread that created a view hierarchy can touch its views.

As far as I can tell I should be accessing the UI thread for this...

I have many working AsyncTasks in my app, but as requested here's the doInBackground (simplified):

for (MediaObject image : toShare)
{
    BufferedInputStream imageData = image.getThumbStream();
    File swapFile = getSwapFile(...);
    write(swapFile, imageData);
    ++completed;
    float progress = (float) completed / toShare.size();
    int progressLocation = (int) Math.ceil(progressRange * progress);
    onProgressUpdate(progressLocation);
}
like image 962
Anthony Avatar asked Mar 05 '13 14:03

Anthony


1 Answers

Okay so the problem is you are calling onProgressUpdate when you should call publishProgress. The OP figured out this himself/herself so I just copy pasted it so he/she does not need to wait to accept the answer. Below is information how AsyncTasks works and it is good knowledge.


Are you creating the AsyncTask on the UI thread? If you are not that is the problem. onProgressUpdate will be run on the thread that created the AsyncTask.

Update: Let us have some code digging time (API 15 source code)!

protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
}

This fellow will call it's static Handler sHandler. The documentation says:

When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

Thanks to Bruno Mateus with his documentation look-up skills:

Look that, i found at documentation page: Threading rules - There are a few threading rules that must be followed for this class to work properly: - The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN. - The task instance must be created on the UI thread. execute(Params...) must be invoked on the UI thread. - Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually. - The task can be executed only once (an exception will be thrown if a second execution is attempted.)

like image 84
Simon Zettervall Avatar answered Sep 22 '22 01:09

Simon Zettervall