Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Método get () de AsyncTask: ¿Existe algún escenario en el que realmente sea la mejor opción?

Después de responder a esta pregunta, tuve una duda sobre el sentido / utilidad de usar el método get () de la clase AsyncTask de Android.

public final Result get () Waits if necessary for the computation to complete, and then retrieves its result. 

Básicamente, una solución síncrona a la clase AsyncTask, que bloquea (congela) la interfaz de usuario hasta que se finalizan las operaciones de fondo.

  • ¿Puedo activar WiFi-Direct desde el código? En la API-14 de Android (ICS)
  • Buscando una explicación de post / pre / set Traducir (en el objeto Matrix) y cómo usarlos
  • ¿Qué significan pivotX y pivotY en animaciones de Android?
  • Deshabilitar Botón cuando Editar Campos de Texto vacío
  • Android añadiendo animaciones simples mientras setvisibility (view.Gone)
  • "IncludeAntRuntime" no se ha establecido para android ant script?
  • Con excepción de los propósitos de la prueba, e incluso en esos casos, no puedo realmente pensar en cualquier situación en donde es realmente una buena solución, pero puedo ser incorrecto, así que me siento curioso.

    Si necesita que el usuario realmente espere hasta que finalice AsyncTask, puede mostrar un Dialog o ProgressDialog, teniendo el control de la interfaz de usuario en cada momento. Sé que no es exactamente lo mismo, pero IMHO es un enfoque mucho mejor que usar el método get() .

  • Actividad de Android que las funciones anuladas deben llamar super. *
  • ¿Cómo se estila la barra de herramientas appcompat-v7 como Theme.AppCompat.Light.DarkActionBar?
  • Establecer posición / tamaño del elemento de la interfaz de usuario como porcentaje del tamaño de la pantalla
  • No recorte las páginas de ViewPager
  • ¿Puede un videoview reproducir un video almacenado en el almacenamiento interno?
  • Android establece varias alarmas
  • 9 Solutions collect form web for “Método get () de AsyncTask: ¿Existe algún escenario en el que realmente sea la mejor opción?”

    AsyncTask no es la única forma de realizar operaciones de fondo. De hecho, la documentación dice que AsyncTask sólo debe ser utilizado para las operaciones de tomar en la mayoría de unos pocos segundos. Así que si tienes tareas que tardan más tiempo, deben ser codificadas a través de clases que implementan la interfaz ejecutables . Tales tareas en otros subprocesos (no AsyncTask) bien pueden querer esperar a que termine una AsyncTask , por lo que me parece que la idea de que no hay situaciones en las que se desee utilizar AsyncTask.get() es falsa.

    Actualización: En respuesta a un comentario, para hacer hincapié en que esto podría ser un uso válido de AsyncTask.get() , lo siguiente es posible:

    • Podría haber AsyncTask que se inicien desde el subproceso de interfaz de usuario, lo que podría implicar la comunicación a través de Internet, por ejemplo, cargar una página web o comunicarse con un servidor. Cualquiera que sean los resultados de AsyncTask , algunos (o todos) de los resultados son necesarios para actualizar la pantalla. Por lo tanto un AsyncTask con su doInBackground seguido por onPostExecute en el hilo de interfaz de usuario tiene sentido.
    • Siempre que el subproceso de interfaz de usuario inicie un AsyncTask , coloca el objeto AsyncTask en una cola, para el procesamiento adicional por un subproceso de fondo independiente una vez que los resultados están disponibles.
    • Para cada AsyncTask en la cola a su vez, el hilo de fondo utiliza AsyncTask.get() para esperar a que finalice la tarea, antes de realizar el procesamiento adicional. Un ejemplo obvio de procesamiento adicional podría ser simplemente registrar todas las actividades de AsyncTask a un servidor en Internet, por lo que tiene sentido hacer esto en segundo plano.

    El siguiente código muestra lo que quiero decir. La aplicación llama a KickOffAsynctask(...) siempre que quiera hacer un AsyncTask, y hay un hilo de fondo que recogerá automáticamente la tarea para el post-procesamiento una vez que la tarea esté completa.

     public class MyActivity extends Activity { static class MyAsyncTaskParameters { } static class MyAsyncTaskResults { } Queue<MyAsyncTask> queue; // task queue for post-processing of AsyncTasks in the background BackgroundThread b_thread; // class related to the background thread that does the post-processing of AsyncTasks @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); queue = new ConcurrentLinkedQueue<MyAsyncTask>(); b_thread = new BackgroundThread(queue); b_thread.Start(); } void KickOffAsynctask(MyAsyncTaskParameters params) { MyAsyncTask newtask = new MyAsyncTask(); newtask.execute(params); synchronized(queue) { queue.add(newtask); } } static class MyAsyncTask extends AsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> { @Override protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) { MyAsyncTaskResults results = new MyAsyncTaskResults(); // do AsyncTask in background return results; } @Override protected void onPostExecute(MyAsyncTaskResults res){ // take required results from MyAsyncResults for use in the user interface } } static class BackgroundThread implements Runnable { // class that controls the post processing of AsyncTask results in background private Queue<MyAsyncTask> queue; private Thread thisthread; public boolean continue_running; public BackgroundThread(Queue<MyAsyncTask> queue) { this.queue=queue; thisthread = null; continue_running = true; } public void Start() { thisthread = new Thread(this); thisthread.start(); } @Override public void run() { try { do { MyAsyncTask task; synchronized(queue) { task = queue.poll(); } if (task == null) { Thread.sleep(100); } else { MyAsyncTaskResults results = task.get(); // post processing of AsyncTask results in background, eg log to a server somewhere } } while (continue_running); } catch(Throwable e) { e.printStackTrace(); } } } } 

    Actualización2 . Se me ha ocurrido otro posible uso válido de AsyncTask.get() . El consejo estándar es no utilizar AsyncTask.get() del hilo de interfaz de usuario, ya que hace que la interfaz de usuario se congele hasta que el resultado esté disponible. Sin embargo, para una aplicación donde stealth se necesita, que puede ser exactamente lo que se requiere. Entonces, ¿qué hay de la siguiente situación: James Bond entra en la habitación del hotel de Le Chiffre y sólo tiene un par de minutos para extraer todos los datos del teléfono del villano e instalar el virus de monitoreo. Él instala la aplicación proporcionada por Q y comienza a correr, pero escucha a alguien que viene por lo que tiene que ocultar. Le Chiffre entra en la habitación y coge su teléfono para hacer una llamada. Por unos segundos el teléfono parece un poco indiferente, pero de repente el teléfono se despierta y hace su llamada telefónica sin pensarlo. Por supuesto, la razón de la falta de respuesta era el hecho de que la aplicación de Q estaba funcionando. Tenía varias tareas que hacer, y algunas de ellas tenían que hacerse en un orden particular. La aplicación utiliza dos subprocesos para realizar el trabajo, es decir, el subproceso de interfaz de usuario y el subproceso de fondo único que procesa AsyncTask . El hilo de interfaz de usuario estaba en el control general de todas las tareas, pero debido a que había que realizar algunas tareas antes de otras tareas, había puntos en la aplicación donde el hilo de interfaz de usuario utilizaba AsyncTask.get() mientras esperaba que la tarea de fondo terminara: ).

    El método get nunca debe ser utilizado en el hilo de la interfaz de usuario, ya que (como notó) congelar su interfaz de usuario. Se debe utilizar en un hilo de fondo para esperar el final de su tarea, pero en general, tratar de evitar AsyncTask tanto como sea posible ( ¿POR QUÉ? ).

    Yo sugeriría una devolución de llamada o eventbus como un reemplazo.

    Si ejecuta varias asyncTasks en paralelo, es posible que desee que algunas tareas esperen el resultado de otras.

    Sin embargo, creo que deberías evitar ejecutar demasiadas asyncTasks en paralelo, porque ralentizará el dispositivo.

    Usualmente uso la clase handler para hacer el truco (Loading media async). Me gusta:

     public void setRightSongAdele(Song current) { RetriveCorrelateGenreSong rcgs = new RetriveCorrelateGenreSong(current); new Thread(rcgs).start(); } @SuppressLint("HandlerLeak") Handler updateRightAdeleHandler = new Handler() { @Override public void handleMessage(Message msg) { songNextText.setText(utils.reduceStringLength(rightSong.getTitle(), 15)); adeleNext.setImageBitmap(utils.getAlbumArtFromSong(rightSong.getPath(), getApplicationContext())); } }; 

    Publico mi propia respuesta, ya que es lo que pienso en este momento y nadie me lo ha dado.

    Mi curiosidad sigue viva, así que no voy a marcar esto como correcto. Si alguien responde brillantemente esta pregunta, marcaré su respuesta como correcta.

    Mi respuesta es que en realidad no hay escenario donde el uso del método get() AsyncTask es la mejor solución.

    IMHO, usar este método es inútil. Lo que quiero decir es que siempre parece que hay una mejor solución.

    Del mismo modo, diría que es semánticamente impactante, ya que llamar cambia su AsyncTask en un eficaz "SyncTask".

    Como se destaca la documentación:

    "Espera si es necesario para completar el cálculo, y luego recupera su resultado".

    Por lo tanto, es obligatorio que evite llamar al subproceso de la interfaz de usuario, de lo contrario obtendrá la NetworkOnMainThreadException . Lo utilizaría en un entorno de prueba que implica operaciones de red o para esperar otra tarea para terminar.

    EDIT: Yo estaba equivocado acerca de NetworkOnMainThreadException .

    Parece como si AsyncTask.get () bloquea el hilo de llamada, donde AsyncTask.execute () no.

    Es posible que desee utilizar AsyncTask.get () para casos de prueba en los que desee probar una determinada llamada de servicio Web, pero no es necesario que sea asíncrona y quiera controlar cuánto tarda en completarse. O en cualquier momento que desee probar contra su servicio web en una suite de pruebas.

    La sintaxis es la misma que execute:

      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)); } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } new DownloadFilesTask().get(5000, TimeUnit.MILLISECONDS); 

    Puede utilizarlo en el filtro del adaptador de AutoCompleteTextView.

     private class Adapter extends BaseAdapter implements Filterable{ getFilter(){ return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { List<String> suggestions = MyApiSuggestionsApi(constraint).get(); return packageAsFilterResults(suggestions); } } } 

    Tengo una aplicación para editar fotos, el usuario es capaz de abrir fotos de las URL.

    Utilicé un AsyncTask para descargar la foto de la URL, durante este tiempo la interfaz de usuario debería ser bloqueada. Lo que hice fue mostrar un ProgressBar inicia el método get () de AsyncTask que ocultar el ProgressBar.

    Parecía la solución mejor y más simple para mí.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.