Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of AsyncTask varargs parameters

What are the reasons that Google use varargs for the parameters in the AsyncTask? For example the methods execute(), doInBackground() and publishProgress() all use the [Type]... notation.

I think that makes it "harder" to use so they must have some good reasons which I overlooked?


So, either we have no parameters, one or many parameters. Let's break it down:

  1. No parameters (easy): Params parameter is Void and that's it. (The methods cannot use it... so that's pretty safe.)

  2. One parameter: Here, I at least, feel the need to make a check at the beginning of the doInBackground() method. For example, here is a task receiving an Integer and producing a result of type Double:

    public Double doInBackground(Integer... myParameters) {
        // we are only expecting one parameter
        if (myParameters.length != 1)
            throw new IllegalArgumentException("!= 1");
    
        return 100d * myParameters[0];
    }
    
  3. More than one parameter. Now here must be where Google made the right choice? But as I see it's either you are interested in a list of parameters of the same type, or you want different types of parameters. Google only addressed one of these cases (with different types you need some kind of common interface. In many cases I end up with Object... and that isn't really type safe...)


So, what is the problem if we just remove the varargs altogether? Here's a subset of the methods:

class AsyncTask<Param, Progress, Result> {

    abstract Result doInBackground(Param param);
    void publishProgress(Progress progress) { ... }
}

This would work for all the cases above. For example, if we want to handle an array of parameters we could just use an array type param:

class MyAsyncTask extends AsyncTask<String[], Integer, String> { 

    String doInBackground(String[] param) {
        return Arrays.toString(param);
    }
}

I don't see when it could be of any practical use. But I'm sure I'm missing something curia that I need to know about. :)

like image 739
dacwe Avatar asked Mar 06 '13 00:03

dacwe


2 Answers

I think the vararg arguments just makes it a bit more convenient when you call to execute the AsyncTask.

As long as we are wondering why AsyncTask was designed the way it is: :-)

In my opinion, the Param and Result templates would not have been really necessary to accomplish the same.

When you write your own AsyncTask, you subclass it. Instead of declaring the actual types for Param and Result, you may as well add final fields to your subclass (Params) and add modifiable fields to your subclass (Result). E.g:

public class MyAsyncTask extends AsyncTask<Void> {
    // Input Params
    private final int inParam1;
    private final String inParam2;

    // Output Results
    private Bitmap resultBitmap;

    public MyAsyncTask(int param1, String param2) {
        inParam1 = param1;
        inParam2 = param2;
    }

    @Override
    protected void doInBackground() {
        // use param1 and param2 as input to the background process.
        ...
        ...
        // Finished: assign to result
        resultBitmap = ....;
    } 

    @Override
    protected void onPostExecute() {
        // Send result to UI.
        ... resultBitmap ...
        ...
        resultBitmap = null;
    }
}

No generics needed, maybe except for showing Progress.

This is what i usually do anyway, especially if the result is a Bitmap. The value returned by doInBackground and handled by onPostExecute is not set to null after all is set and done and it sneakily 'leaks' Bitmaps this way (memory errors caused by bitmaps held in memory by completed/finished AsyncTasks).

like image 78
Streets Of Boston Avatar answered Oct 03 '22 17:10

Streets Of Boston


I think you are right, the only usage of the type parameter Params is in Params..., which implies that it is really the Params[] that is wanted here. However now the API only works with array types, it misses a whole lot of non-array types.

The only advantage of varargs is at the call site, but it's not much either -

Google's version:

AsyncTask<String> task = ...
task.execute("a", "b");

Your version:

AsyncTask<List<String>> task = ...
task.execute(Arrays.asList("a", "b"));
like image 25
irreputable Avatar answered Oct 03 '22 19:10

irreputable