Skip to content Skip to sidebar Skip to footer

Asynctask's Get() Method: Is There Any Scenario Where It Is Actually The Best Option?

After answering this question, I got a doubt about the sense/usefulness of using the get() method of Android's AsyncTask class. public final Result get () Waits if necessary for

Solution 1:

AsyncTask isn't the only way of doing background operations. Indeed, the documentation says that AsyncTask should only be used for operations take at most a few seconds. So if you've got tasks that take longer, they should be coded via classes that implement the runnable interface. Such tasks in other (non AsyncTask) threads may well want to wait for an AsyncTask to finish, so it seems to me that the idea that there are no situations where one would want to use AsyncTask.get() is false.

Update: In response to a comment, to emphasize that this could be a valid use of AsyncTask.get(), the following is possible:

  • There could be AsyncTasks that get initiated from the UI thread, which might involve communicating over the internet, e.g. loading a web page, or communicating with a server. Whatever the results of the AsyncTask are, some (or all) of the results are needed to update the screen. Hence an AsyncTask with its doInBackground followed by onPostExecute on the UI thread makes sense.
  • Whenever the UI thread initiates an AsyncTask, it places the AsyncTask object in a queue, for additional processing by a separate background thread once the results are available.
  • For each AsyncTask in the queue in turn, the background thread uses AsyncTask.get() to wait for the task to finish, before doing the additional processing. One obvious example of additional processing could simply be logging all such AsyncTask activities to a server on the internet, so it makes sense to do this in the background.
The following code shows what I mean. The app calls KickOffAsynctask(...) whenever it wants to do an AsyncTask, and there's a background thread that will automatically pickup the task for post-processing once the task is complete.
publicclassMyActivityextendsActivity {

    staticclassMyAsyncTaskParameters { }
    staticclassMyAsyncTaskResults { }

    Queue<MyAsyncTask> queue;   // task queue for post-processing of AsyncTasks in the background
    BackgroundThread b_thread;  // class related to the background thread that does the post-processing of AsyncTasks@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     
        queue = newConcurrentLinkedQueue<MyAsyncTask>();
        b_thread = newBackgroundThread(queue);
        b_thread.Start();       
    }

    voidKickOffAsynctask(MyAsyncTaskParameters params) {
        MyAsyncTasknewtask=newMyAsyncTask();
        newtask.execute(params);
        synchronized(queue) {
            queue.add(newtask);
        }
    }

    staticclassMyAsyncTaskextendsAsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> {

        @Overrideprotected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) {
            MyAsyncTaskResultsresults=newMyAsyncTaskResults();
            // do AsyncTask in backgroundreturn results;
        }

        @OverrideprotectedvoidonPostExecute(MyAsyncTaskResults res){
            // take required results from MyAsyncResults for use in the user interface
        }

    }

    staticclassBackgroundThreadimplementsRunnable {
        // class that controls the post processing of AsyncTask results in backgroundprivate Queue<MyAsyncTask> queue;
        private Thread thisthread;
        publicboolean continue_running;

        publicBackgroundThread(Queue<MyAsyncTask> queue) {
            this.queue=queue; thisthread = null; continue_running = true;
        }

        publicvoidStart() {
            thisthread = newThread(this);
            thisthread.start();
        }

        @Overridepublicvoidrun() {
            try {
                do {
                    MyAsyncTask task;
                    synchronized(queue) {
                        task = queue.poll();
                    }
                    if (task == null) {
                        Thread.sleep(100);
                    } else {
                        MyAsyncTaskResultsresults= task.get();
                        // post processing of AsyncTask results in background, e.g. log to a server somewhere
                    }
                } while (continue_running);     
            } catch(Throwable e) {
                e.printStackTrace();
            }           
        }

    }

}

Update2. Another possible valid use of AsyncTask.get() has occurred to me. The standard advice is not to use AsyncTask.get() from the UI thread, because it causes the user interface to freeze until the result is available. However, for an app where stealth is needed, that may be exactly what is required. So how about the following situation: James Bond breaks into the hotel room of Le Chiffre and only has a couple of minutes to extract all the data from the villian's phone and install the monitoring virus. He installs the app provided by Q and starts it running, but he hears someone coming so he has to hide. Le Chiffre enters the room and picks up his phone to make a call. For a few seconds the phone seems a bit unresponsive, but suddenly the phone wakes up and he makes his phone call without further thought. Of course, the reason for the unresponsiveness was the fact that Q's app was running. It had various tasks to do, and some of them needed to be done in a particular order. The app used two threads to do the work, namely the UI thread itself and the single background thread that processes AsyncTasks. The UI thread was in overall control of all the tasks, but because some tasks needed to be done before other tasks, there were points in the app where the UI thread used AsyncTask.get() while waiting for the background task to finish :-).

Solution 2:

The get method should never be used in the UI thread because it will (as you noticed) freeze your UI. It should be used in a background thread to wait for the end of your task, but generally speaking, try to avoid AsyncTask as much as possible (WHY?).

I would suggest a callback or eventbus as a replacement.

Solution 3:

if you run multiple asyncTasks in parallel , you might want that some tasks would wait for the result of others.

however, i think you should avoid running too many asyncTasks in parallel, because it will slow down the device.

Solution 4:

I usually use the handler class to do the trick (Loading media async). Like:

publicvoidsetRightSongAdele(Song current)
{
    RetriveCorrelateGenreSongrcgs=newRetriveCorrelateGenreSong(current);
    newThread(rcgs).start();
}

@SuppressLint("HandlerLeak")HandlerupdateRightAdeleHandler=newHandler()
{
    @OverridepublicvoidhandleMessage(Message msg) {
        songNextText.setText(utils.reduceStringLength(rightSong.getTitle(), 15));
        adeleNext.setImageBitmap(utils.getAlbumArtFromSong(rightSong.getPath(), getApplicationContext()));
    }
};

Solution 5:

I post my own answer, as it is what I think at this moment and nobody has given it.

My curiosity is still alive, so I wont mark this one as correct. If someone answers this question brilliantly, I will mark his/her answer as correct.

My answer is that there is actually no scenario where using the AsyncTask's get() method is the best solution.

IMHO, using this method is pointless. What I mean is that there always seem to be a better solution.

Likewise, I would say it's semantically shocking, as calling it changes your AsyncTask into an effective "SyncTask".

Post a Comment for "Asynctask's Get() Method: Is There Any Scenario Where It Is Actually The Best Option?"