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:
No parameters (easy): Params
parameter is Void
and that's it. (The methods cannot use it... so that's pretty safe.)
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];
}
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. :)
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
).
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"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With