¿Cómo se pueden pasar múltiples parámetros primitivos a AsyncTask?

Hay preguntas relacionadas, como ¿Cómo puedo pasar dos parámetros a una clase AsyncTask? , pero me encontré con la dificultad de intentar en vano pasar múltiples primitivos como parámetros a una AsyncTask, por lo que quiero compartir lo que descubrí. Esta sutileza no se capta en las preguntas y respuestas existentes, por lo que quiero ayudar a cualquiera que se encuentre con el mismo problema que yo y salvarles el dolor.

La pregunta es: tengo varios parámetros primitivos (por ejemplo, dos largos) que quiero pasar a una AsyncTask para que se ejecute en segundo plano. ¿Cómo se puede hacer? (Mi respuesta … después de luchar con esto por un tiempo … se puede encontrar a continuación).

Simplemente envuelva sus primitivos en un contenedor simple y pase eso como un parámetro a AsyncTask, así:

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 { @Override protected void doInBackground(MyTaskParams... params) { int foo = params[0].foo; long bar = params[0].bar; double arple = params[0].arple; ... } } 

Llámalo así:

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

Otra forma: solo necesitas agregar el constructor MyTask en tu clase MyTask:

 private class MyTask extends AsyncTask { 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 } 

Luego llame

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

Una segunda forma como la Respuesta de David Wasser.

Es (estrictamente hablando) NO es posible pasar múltiples primitivos a AsyncTask. Por ejemplo, si desea realizar myTask.execute(long1, long2) y tratar de configurar una private class myTask extends AsyncTask con el método correspondiente:

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

su IDE probablemente se quejará sobre la necesidad de anular un método de supertipo. Tenga en cuenta que está utilizando la llamada firma de método Varargs para doInBackground , donde (long... params) es como decir “Acepto un número variable de longs, almacenado como una matriz llamada params. No entiendo completamente las causas una queja comstackdor / IDE que se planteará, pero creo que tiene que ver con cómo se define la clase genérica de Params .

En cualquier caso, es posible lograr lo que quiera sin ningún problema, siempre que envíe correctamente sus primitivas a sus respectivas envolturas no primitivas (por ejemplo, int => Integer, long => Long, etc.). En realidad, no es necesario que expliqué explícitamente sus primitivos a no primitivos. Java parece manejar eso por ti. Solo necesita configurar su ASyncTask de la siguiente manera (para el ejemplo de longs):

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

A continuación, puede utilizar esta clase como originalmente se pretendía, por ejemplo:

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

O para cualquier número de primitivos que desee, SIEMPRE SON DEL MISMO TIPO. Si necesita pasar múltiples tipos de primitivos, esto también se puede hacer, pero deberá modificar lo anterior para:

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

Esto es más flexible, pero requiere emitir explícitamente los parámetros a sus respectivos tipos. Si no se necesita esta flexibilidad (es decir, un solo tipo de datos), recomiendo seguir con la primera opción, ya que es un poco más legible.

Me gusta el método de malajisi, pero si no lo hiciste, ¿no podrías usar la clase Bundle?

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

Luego solo pasa el paquete y descomprímelo dentro de MyTask. ¿Es esta una idea terrible? Evita crear una clase personalizada, y es flexible si decide que necesita pasar parámetros adicionales más adelante.

El método de ejecución integrado acepta una matriz de Params, pero todos deben ser del tipo definido. Por lo tanto, si simplemente configura el tipo PARAM para OBJECT, puede pasar lo que quiera siempre que sean hijos de objetos. …

 private class MyTask extends AsyncTask { 

Luego, en tu doInBackGround, simplemente echas cada parámetro en orden a lo que necesitas que sea:

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

Y tu ejecución es simple:

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

No es tan bueno como envolverlo en su propia clase contenedora, o un paquete, o hash o algo así, porque depende de ambos lados, pero funcionará. Por supuesto, podrías hacer que tu matriz sea un param de HashMap (,) y básicamente implementes un paquete personalizado en ese punto, pero funcionará.

Esto se resuelve mediante subclases. Google tiene un ejemplo para resolver este problema (subclases) en la documentación oficial AsyncTask de Android:

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

Ejemplo:

 private class DownloadFilesTask extends AsyncTask { 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"); } }