Подтвердить что ты не робот

Назначение параметров varargs AsyncTask

Каковы причины, по которым Google использует varargs для параметров в AsyncTask? Например, методы execute(), doInBackground() и publishProgress() все используют нотацию [Type]....

Я думаю, что это делает его "труднее", поэтому у них должны быть некоторые веские причины, которые я забыл?


Таким образом, либо у нас нет параметров, ни одного или многих параметров. Позвольте сломать его:

  • Нет параметров (легко): Params параметр Void и что он. (Методы не могут использовать его... так что это довольно безопасно.)

  • Один параметр. Здесь, по крайней мере, я чувствую необходимость сделать проверку в начале метода 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];
    }
    
  • Более одного параметра. Теперь должно быть, где Google сделал правильный выбор? Но, как я вижу, вас либо интересует список параметров того же типа, либо вам нужны разные типы параметров. 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);
    }
}

Я не вижу, когда это может быть практическим. Но я уверен, что мне не хватает чего-то курии, о которой я должен знать.:)

4b9b3361

Ответ 1

Я думаю, что аргументы vararg просто делают его более удобным, когда вы вызываете для выполнения AsyncTask.

Пока нам интересно, почему AsyncTask был спроектирован так:: -)

По-моему, шаблоны Param и Result не были бы действительно необходимы для выполнения того же самого.

Когда вы пишете свой собственный AsyncTask, вы подклассифицируете его. Вместо объявления реальных типов для Param и Result вы также можете добавить конечные поля в свой подкласс (Params) и добавить модифицируемые поля в ваш подкласс (результат). Например:

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

Ответ 2

Я думаю, что вы правы, единственное использование параметра типа Params находится в Params..., что означает, что это действительно Params[], который здесь нужен. Однако теперь API работает только с типами массивов, он пропускает множество типов без массивов.

Единственное преимущество varargs - на сайте вызова, но это не так много -

Версия Google:

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

Ваша версия:

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