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


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

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

6 61

6 ответов:

просто оберните свои примитивы в простой контейнер и передайте это в качестве параметра в 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);

другой способ: вам просто нужно добавить конструктор 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();

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

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

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

ваша IDE, скорее всего, будет жаловаться на необходимость переопределения метода супертипа. Обратите внимание, что вы используете так называемый Varargs сигнатуру метода для doInBackground, где (long... params) это как сказать: "Я принимаю переменное число лонгов, хранящихся в виде массива, называемого 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];

    }
    ...
}

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

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

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

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

встроенный метод execute принимает массив параметров, но все они должны быть определенного типа.. поэтому, если вы просто установите тип PARAM в OBJECT, вы можете передавать все, что вам нравится, пока они являются дочерними объектами....

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

затем в вашем doInBackGround вы просто бросаете каждый парам, чтобы вернуться к тому, что вам нужно:

 @Override
 protected void doInBackground(Object... params) {
     Context t = (Context)parms[0];
     String a = (String) params[1];
     List<LatLng> list = (List<LatLng>)params[2];
     .
     .
     .

и ваш выполнить просто:

 new MyTask().execute(context,somestring,list_of_points);

не так хорошо, как обернуть его в свою собственную обертку класс, или связка, или хэш или что-то еще, потому что вы зависите от порядка с обеих сторон, но это будет работать. Конечно, вы можете просто сделать свой массив параметром HashMap (,), и вы в основном настраиваете реализацию пакета в этот момент, но он будет работать.

это решается с помощью подклассов. У 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");
    }
}