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

Как вы можете передать несколько примитивных параметров AsyncTask?

Есть связанные вопросы, такие как Как передать 2 параметра классу AsyncTask?, но я столкнулся с трудностью тщетно пытаться передать несколько примитивов в качестве параметров AsyncTask, поэтому хочу поделиться тем, что я обнаружил. Эта тонкость не фиксируется в существующих вопросах и ответах, поэтому я хочу помочь любому, кто сталкивается с той же проблемой, что и я, и избавить их от боли.

Вопрос в следующем: у меня есть несколько примитивных параметров (например, две длинные), которые я хочу передать в AsyncTask для выполнения в фоновом режиме - как это можно сделать? (Мой ответ... после битвы с этим на некоторое время... можно найти ниже.)

4b9b3361

Ответ 1

Это (строго говоря) НЕ возможно передать несколько примитивов в AsyncTask. Например, если вы хотите выполнить myTask.execute(long1, long2) и попытаться настроить private class myTask extends AsyncTask<long, Void, Void> с помощью соответствующего метода:

@Override
protected LocationItemizedOverlay doInBackground(long... params) {...}

ваша IDE, скорее всего, будет жаловаться на необходимость переопределить метод супертипа. Обратите внимание, что вы используете так называемую подпись Varargs для doInBackground, где (long... params) похоже на высказывание" Я принимаю переменную количество длин, хранящихся в массиве с параметрами. Я не совсем понимаю, что вызывает жалобу на компилятор /IDE, но я думаю, что это связано с тем, как определяется общий класс Params.

В любом случае можно добиться того, чего вы хотите без проблем, при условии, что вы правильно применили свои примитивы к своим не примитивным оберткам (например, int = > Integer, long = > Long и т.д.). Фактически, вам не нужно явно передавать ваши примитивы в непримитивы. Java, похоже, справится с этим для вас. Вам просто нужно настроить ASyncTask следующим образом (для примера longs):

private class MyTask extends AsyncTask<Long, Void, Void> {

    @Override
    protected void doInBackground(Long... params) {
        // Do stuff with params, for example:
        long myFirstParam = params[0]
    }
    ...
}

Затем вы можете использовать этот класс по своему усмотрению, например:

MyTask myTask = new MyTask();
myTask.execute(long1, long2);

Или для любого количества примитивов, которые вы хотели бы, ПРЕДОСТАВЛЯЕМЫЕ ОНИ ТАКИГО ТИПА. Если вам нужно передать несколько типов примитивов, это также можно сделать, но вам нужно будет изменить приведенное выше:

private class MyTask extends AsyncTask<Object, Void, Void> {

    @Override
    protected void doInBackground(Object... params) {
        // Do stuff with params, for example:
        long myLongParam = (Long) params[0];
        int myIntParam = (Integer) params[1];

    }
    ...
}

Это более гибко, но для этого требуется явно вводить параметры в соответствующие типы. Если эта гибкость не нужна (т.е. Один тип данных), я рекомендую придерживаться первого варианта, так как он немного читаем.

Ответ 2

Просто оберните примитивы в простой контейнер и передайте это как параметр AsyncTask, например:

private static class MyTaskParams {
    int foo;
    long bar;
    double arple;

    MyTaskParams(int foo, long bar, double arple) {
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
}

private class MyTask extends AsyncTask<MyTaskParams, Void, Void> {
    @Override
    protected void doInBackground(MyTaskParams... params) {
        int foo = params[0].foo;
        long bar = params[0].bar;
        double arple = params[0].arple;
        ...
    }
}

Назовите его следующим образом:

MyTaskParams params = new MyTaskParams(foo, bar, arple);
MyTask myTask = new MyTask();
myTask.execute(params);

Ответ 3

Другой способ: вам просто нужно добавить конструктор MyTask в свой класс MyTask:

private class MyTask extends AsyncTask<String, Void, Void> {
    int foo;
    long bar;
    double arple;

    MyTask(int foo, long bar, double arple) { 
         // list all the parameters like in normal class define
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
    ......   // Here is doInBackground etc. as you did before
}

Затем вызовите

new MyTask(int foo, long bar, double arple).execute();

Второй способ, как Дэвид Вассер.

Ответ 4

Мне нравится метод malajisi, но если вы этого не сделали, не могли бы вы использовать класс Bundle?

 Bundle myBundle = new Bundle();
 myBundle.putInt("foo", foo);
 myBundle.putLong("bar", bar);
 myBundle.putDouble("arple", arple);

Затем просто передайте пакет и распакуйте его внутри MyTask. Это ужасная идея? Вы избегаете создания пользовательского класса, и это гибко, если вы решите, что вам нужно передать дополнительные параметры позже.

Ответ 5

Это решается посредством подкласса. В Google есть пример для решения этой проблемы (подклассификация) в официальной документации на Android AsyncTask:

http://developer.android.com/reference/android/os/AsyncTask.html

Пример:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
}