【问题标题】:Purpose of AsyncTask varargs parametersAsyncTask 可变参数的用途
【发布时间】:2013-02-20 14:32:47
【问题描述】:

Google 使用varargs 作为AsyncTask 中的参数的原因是什么?例如execute()doInBackground()publishProgress() 方法都使用[Type]... 表示法。

我认为这使得它“更难”使用,所以他们一定有一些我忽略的充分理由?


所以,要么我们没有参数,要么有一个参数,要么有多个参数。让我们分解一下:

  1. 无参数(简单):Params 参数为Void,仅此而已。 (这些方法不能使用它......所以这很安全。)

  2. 一个参数:在这里,我至少觉得有必要在doInBackground()方法的开头做个检查。例如,这是一个接收Integer 并产生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. 多个参数。现在这里一定是谷歌做出正确选择的地方吗?但正如我所见,您要么对相同类型的参数列表感兴趣,要么想要不同类型的参数。 Google 只解决了其中一种情况(对于不同的类型,您需要某种通用接口。在许多情况下,我最终会得到 Object...,这并不是真正的类型安全...)


那么,如果我们完全删除 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);
    }
}

我看不出它什么时候会有实际用途。但我确定我错过了一些我需要知道的东西。 :)

【问题讨论】:

  • 为什么这个问题与那个问题重复?这是我正在质疑的特定界面。开发人员为什么要使用可变参数来解决这个特定问题。我想我已经明确表示我知道它是什么,并且我会在适当的时候使用它.. :)
  • “这是一个我在质疑的特定接口”——你的论点中没有任何与 AsyncTask 有任何特定关系的东西。您可能会抱怨在 Restaurant 类中使用可变参数。如果您的问题集中在可变参数对AsyncTask 如何处理线程之间的通信的影响上,那么它可能不是重复的。但是,就目前而言,恕我直言,我引用的问题中提出的答案似乎也涵盖了这个问题。
  • 此外,“Google 使用可变参数作为参数的原因”是无法回答的,除非我们能说服 Romain Guy(AsyncTask 的原作者)加入这个问题。对于为什么在这种情况下使用可变参数的答案,最接近的答案是通常会使用可变参数的答案,这在链接到的问题中有所介绍。

标签: java android android-asynctask


【解决方案1】:

我认为 vararg 参数只是让您调用执行AsyncTask 时更加方便。

只要我们想知道为什么 AsyncTask 是这样设计的::-)

在我看来,ParamResult 模板对于完成同样的事情并不是真正必要的。

当您编写自己的AsyncTask 时,您将其子类化。与其声明ParamResult 的实际类型,不如将final 字段添加到您的子类(Params)并将可修改字段添加到您的子类(Result)。例如:

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

不需要泛型,也许除了显示进度。

这是我通常会做的事情,特别是如果结果是BitmapdoInBackground 返回并由onPostExecute 处理的值在所有设置和完成后未设置为null,它以这种方式偷偷地“泄漏”Bitmaps(由完成/完成@987654332 保存在内存中的位图引起的内存错误@)。

【讨论】:

    【解决方案2】:

    我认为你是对的,类型参数Params 的唯一用法是在Params... 中,这意味着这里真正需要的是Params[]。但是现在 API 只适用于数组类型,它遗漏了很多非数组类型。

    可变参数的唯一优势在于调用站点,但也不是很多 -

    谷歌版本:

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

    你的版本:

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

    【讨论】:

      猜你喜欢
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 2018-01-13
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多