AsyncTask varargs 参数的目的

15
什么是谷歌在AsyncTask参数中使用varargs的原因?例如,方法execute()doInBackground()publishProgress()都使用[Type]...符号。我认为这使得它更难使用,所以他们一定有一些好的理由,我可能忽略了些什么?

因此,我们要么没有参数,要么有一个或多个参数。让我们分解一下:

  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...)


那么,如果我们完全删除varargs会有什么问题呢?这是一些方法的子集:

class AsyncTask<Param, Progress, Result> {

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

这对以上所有情况都适用。例如,如果我们想处理参数数组,我们只需使用数组类型param:
class MyAsyncTask extends AsyncTask<String[], Integer, String> { 

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

我不认为它有任何实际应用价值。但我相信我可能错过了某些需要了解的关于curia的东西。:)


1
为什么这个问题被认为是那个问题的重复?我在询问一个特定的接口。开发人员为什么要在这个特定问题中使用可变参数?我想我已经清楚表明我知道它是什么,并且在适当的时候我也会使用它.. :) - dacwe
这是我在质疑的特定接口 - 你的论点与AsyncTask没有任何具体关系。你可能会抱怨使用Restaurant类的可变参数。如果你的问题集中在可变参数对AsyncTask如何处理线程间通信的影响上,那么它可能不是一个重复的问题。但就目前而言,在我看来,我引用的问题中提供的答案似乎也可以回答这个问题。 - CommonsWare
此外,“谷歌使用可变参数的原因”是无法回答的,除非我们能说服 AsyncTask 的原作者Romain Guy加入这个问题的讨论。关于为什么在这种情况下使用可变参数的答案最接近的是为什么一般会使用可变参数的答案,该问题已在链接的问题中得到解答。 - CommonsWare
哈哈!这就解决了!我从现在开始就会使用它。但我有点难过,因为这不是我不知道的东西。再次感谢! - dacwe
10
https://twitter.com/romainguy/status/309102518569410560 - a.bertucci
显示剩余3条评论
2个回答

2

我认为可变参数只是在调用AsyncTask时更加方便。

就我个人而言,ParamResult模板并不是必要的。

当你编写自己的AsyncTask时,你需要继承它。你可以在你的子类中添加final字段(Params)和可修改的字段(Result),而不是声明ParamResult的实际类型。例如:

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;
    }
}

除了显示进度条之外,不需要使用泛型。

通常我会这样做,特别是如果结果是Bitmap。在所有操作完成后,doInBackground返回的值由onPostExecute处理,完成后不会设置为null,这种方式会“泄漏”Bitmaps(由已完成/已结束的AsyncTasks保留在内存中的位图导致的内存错误)。


1
我认为你是正确的,类型参数Params唯一的使用场景在于Params...,这意味着这里真正需要的是Params[]。然而现在API只能使用数组类型,错过了很多非数组类型。
可变参数的唯一优点在于调用方,但也不是很大——
Google的版本:
AsyncTask<String> task = ...
task.execute("a", "b");

您的版本:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接