studio - oncancelled asynctask android




Controlador vs AsyncTask vs Hilo (8)

Me confundí un poco acerca de las diferencias entre Handlers , AsyncTask y Threads en Android. He leído bastantes blogs y preguntas aquí en stackoverflow.

Handler son hilos en segundo plano que le permiten comunicarse con la interfaz de usuario. La actualización de una barra de progreso, por ejemplo, debe hacerse a través del Handler . Al usar Handlers, tiene la ventaja de MessagingQueues , por lo tanto, si desea programar mensajes o actualizar múltiples elementos de UI o tiene tareas repetitivas.

AsyncTask son similares, de hecho, utilizan Handler , pero no se ejecutan en el subproceso de la interfaz de usuario, por lo que es bueno para obtener datos, por ejemplo, para obtener servicios web. Más tarde podrás interactuar con la interfaz de usuario.

Sin embargo, el Thread no puede interactuar con la interfaz de usuario, proporciona más subprocesos "básicos" y se pierden todas las abstracciones de AsyncTask .

Sin embargo, me gustaría tener una conexión de socket ejecutada en un servicio. ¿Debería ejecutarse esto en un controlador o un hilo, o incluso en una AsyncTask ? La interacción de la interfaz de usuario no es necesaria en absoluto. ¿Hace una diferencia en términos de rendimiento que uso?

Mientras tanto, la documentation ha sido mejorada en gran medida.


Como el Tutorial sobre el procesamiento en segundo plano de Android con manejadores, AsyncTask y Loaders en el sitio de Vogella lo pone:

La clase Handler puede usarse para registrarse en un hilo y proporciona un canal simple para enviar datos a este hilo.

La clase AsyncTask encapsula la creación de un proceso en segundo plano y la sincronización con el hilo principal. También es compatible con los informes de progreso de las tareas en ejecución.

Y un Thread es básicamente el elemento central del multiproceso que un desarrollador puede usar con la siguiente desventaja:

Si usa subprocesos de Java, debe manejar los siguientes requisitos en su propio código:

  • Sincronización con el hilo principal si devuelve resultados a la interfaz de usuario
  • No predeterminado para cancelar el hilo
  • Sin agrupación de hilos por defecto
  • No predeterminado para manejar cambios de configuración en Android

Y con respecto a AsyncTask , como lo AsyncTask documentation :

AsyncTask permite el uso correcto y fácil del hilo de la interfaz de usuario. Esta clase permite realizar operaciones en segundo plano y publicar resultados en el subproceso de la interfaz de usuario sin tener que manipular subprocesos y / o controladores.

AsyncTask está diseñado para ser una clase auxiliar en torno a Thread y Handler y no constituye un marco de subprocesamiento genérico. Se recomienda utilizar AsyncTasks para operaciones cortas (como mínimo, unos segundos). Si necesita mantener los subprocesos en ejecución durante largos períodos de tiempo, se recomienda encarecidamente que utilice las diversas API proporcionadas por el paquete java.util.concurrent, como Ejecutor, ThreadPoolExecutor y FutureTask.

Actualización de mayo de 2015: encontré una excelente serie de conferencias sobre este tema.

Esta es la búsqueda de Google: Douglas Schmidt conferencia androide concurrencia y sincronización

Este es el video de la primera conferencia en YouTube.

Todo esto es parte del CS 282 (2013): Programación de sistemas para Android de la Universidad de Vanderbilt . Aquí está la lista de reproducción de YouTube

Douglas Schmidt parece ser un excelente profesor

Importante: si se encuentra en un punto en el que está considerando usar AsyncTask para resolver sus problemas de subprocesos, primero debe revisar ReactiveX/RxAndroid para un patrón de programación posiblemente más apropiado. Un buen recurso para obtener una visión general es Aprender RxJava 2 para Android por ejemplo .


Después de mirar en profundidad, es sencillo.

AsyncTask :

Es una forma sencilla de usar un hilo sin saber nada sobre el modelo de hilo de Java . AsyncTask proporciona varias devoluciones de llamada respectivas al subproceso de trabajo y al subproceso principal.

Use para operaciones de espera pequeñas como las siguientes:

  1. Obtención de algunos datos de servicios web y visualización sobre diseño.
  2. Consulta de base de datos.
  3. Cuando te das cuenta de que la operación en ejecución nunca será anidada.

Handler

Cuando instalamos una aplicación en Android, creará un subproceso para esa aplicación llamada MAIN UI Thread. Todas las actividades se ejecutan dentro de ese hilo. Mediante la regla del modelo de un solo hilo de Android, no podemos acceder a los elementos de la IU (mapa de bits, vista de texto, etc.) directamente para otro hilo definido dentro de esa actividad.

Un controlador le permite comunicarse de nuevo con el hilo de la interfaz de usuario de otro hilo de fondo. Esto es útil en Android ya que Android no permite que otros subprocesos se comuniquen directamente con el subproceso de la interfaz de usuario. El controlador puede enviar y procesar los objetos Message y Runnable asociados con MessageQueue de un subproceso. Cada instancia de Handler está asociada con un solo hilo y la cola de mensajes de ese hilo. Cuando se crea un nuevo controlador, se vincula a la cola de subprocesos / mensajes del subproceso que lo está creando.

Es la mejor opción para:

  1. Te permite hacer colas de mensajes.
  2. Programación de mensajes.

Thread :

Ahora es el momento de hablar de hilo.

El hilo es el padre de AsyncTask y Handler . Ambos utilizan internamente subprocesos, lo que significa que también puede crear su propio modelo de subprocesos como AsyncTask y Handler , pero eso requiere un buen conocimiento de la implementación de subprocesos múltiples de Java .


Se AsyncTask una AsyncTask para realizar algunos cálculos en segundo plano y publicar el resultado en el subproceso de la interfaz de usuario (con actualizaciones de progreso opcionales). Como no le preocupa la interfaz de usuario, entonces un Handler o un Thread parece más apropiado.

Puede generar un Thread fondo y pasar mensajes de vuelta a su subproceso principal utilizando el método de post Controlador.


Si observa el código fuente de AsyncTask and Handler , verá que su código está escrito únicamente en Java. (Por supuesto, hay algunas excepciones, pero ese no es un punto importante).

Así que no hay magia en AsyncTask o Handler . Simplemente hacen su trabajo más fácil como desarrollador.

Por ejemplo: si el Programa A llama al método A (), el método A () podría ejecutarse en un hilo diferente con el Programa A. Puede verificarlo fácilmente usando:

Thread t = Thread.currentThread();    
int id = t.getId();

¿Por qué deberías usar un nuevo hilo? Puede google para ello. Muchas muchas razones.

Entonces, ¿cuál es la diferencia entre Thread , AsyncTask y Handler ?

AsyncTask y Handler están escritos en Java (internamente usan un Thread ), por lo que todo lo que puede hacer con Handler o AsyncTask , también puede lograr el uso de un Thread .

¿En qué pueden AsyncTask realmente Handler y AsyncTask ?

La razón más obvia es la comunicación entre el subproceso de la persona que llama y el subproceso de trabajo. ( Subproceso de llamada : un subproceso que llama al subproceso de trabajo para realizar alguna tarea. Un subproceso de llamada no necesariamente tiene que ser el subproceso de la interfaz de usuario). Por supuesto, puede comunicarse entre dos hilos de otras maneras, pero existen muchas desventajas (y peligros) debido a problemas de seguridad de los hilos.

Es por eso que debes usar Handler y AsyncTask . Hacen la mayor parte del trabajo por usted, solo necesita saber qué métodos anular.

La diferencia entre Handler y AsyncTask es: usar AsyncTask cuando el subproceso de la persona que llama es un subproceso de la interfaz de usuario . Esto es lo que dice el documento de Android:

AsyncTask permite el uso correcto y fácil del hilo de la interfaz de usuario. Esta clase permite realizar operaciones en segundo plano y publicar resultados en el subproceso de la interfaz de usuario sin tener que manipular subprocesos y / o controladores

Quiero enfatizar en dos puntos:

1) Uso sencillo del hilo de la interfaz de usuario (por lo tanto, use cuando el hilo de la persona que llama es hilo de la interfaz de usuario).

2) No es necesario manipular los manipuladores. (significa: puede usar Handler en lugar de AsyncTask, pero AsyncTask es una opción más fácil).

Hay muchas cosas en esta publicación que aún no he dicho, por ejemplo: qué es el hilo de la interfaz de usuario o por qué es más fácil. Debe conocer algún método detrás de cada tipo y utilizarlo, entenderá completamente por qué ..

@: cuando lees el documento de Android, verás:

El controlador le permite enviar y procesar objetos Message y Runnable asociados con MessageQueue de un hilo

Pueden parecer extraños al principio. Simplemente entienda que cada hilo tiene cada cola de mensajes (como una lista de tareas pendientes), y el hilo tomará cada mensaje y lo hará hasta que la cola de mensajes esté vacía (al igual que usted termina su trabajo y se va a la cama). Entonces, cuando Handler comunica, solo le da un mensaje al hilo de la persona que llama y esperará para procesarlo. ¿Complicado? Solo recuerde que Handler puede comunicarse con el hilo de la persona que llama de una manera segura.


AsyncTask está diseñado para realizar una operación de no más de unos pocos segundos en segundo plano (no se recomienda para megabytes de descarga de archivos desde el servidor o la tarea de procesamiento de la CPU, como las operaciones de E / S de archivos). Si necesita ejecutar una operación de ejecución prolongada, se le ha recomendado encarecidamente que use subprocesos nativos java. Java te da varias clases relacionadas con hilos para hacer lo que necesitas. Utilice el Handler para actualizar el subproceso de la interfaz de usuario.


Handler - es un medio de comunicación entre hilos. En Android, se utiliza principalmente para comunicarse con el hilo principal al crear y enviar mensajes a través del controlador.

AsyncTask : se utiliza para realizar aplicaciones de larga ejecución en un hilo de fondo. Con n AsyncTask , puede realizar la operación en un subproceso en segundo plano y obtener el resultado en el subproceso principal de la aplicación.

Thread : es un proceso ligero para lograr la concurrencia y la utilización máxima de la CPU. En Android, puedes usar un hilo para realizar actividades que no toquen la interfaz de usuario de la aplicación


Permítame intentar responder a la pregunta aquí con un ejemplo :) - MyImageSearch [Consulte amablemente la imagen aquí de la pantalla de actividad principal, que contiene un texto de edición / botón de búsqueda / vista de cuadrícula]

Descripción de MyImageSearch : una vez que el usuario ingrese los detalles en el campo de edición de texto y haga clic en el botón de búsqueda, buscaremos imágenes en Internet a través de los servicios web proporcionados por flickr (solo necesita registrarse allí para obtener una clave / token secreto) - para la búsqueda, enviamos una solicitud HTTP y GET JSON Data en respuesta que contiene las direcciones URL de las imágenes individuales que luego utilizaremos para cargar la vista de cuadrícula.

Mi implementación : en la actividad principal definiré una clase interna que extienda AsyncTask para enviar la Solicitud HTTP en el Método doInBackGround y obtener la Respuesta JSON y actualizar mi ArrayList local de FlickrItems, que voy a usar para actualizar mi GridView a través del adaptador de Flickr. (extiende el Adaptador base) y llame al adapter.notifyDataSetChanged () en el onPostExecute () de AsyncTask para volver a cargar la vista de cuadrícula. Tenga en cuenta que aquí la solicitud HTTP es una llamada de bloqueo debido a que lo he hecho a través de AsyncTask. Y puedo almacenar en caché los elementos en el adaptador para aumentar el rendimiento o almacenarlos en la tarjeta SD. La cuadrícula que voy a inflar en el adaptador de Flickr contiene en mi implementación una barra de progreso y una vista de imagen. A continuación puede encontrar el código de mainActivity que utilicé.

Responda a la pregunta ahora . Entonces, una vez que tengamos los datos JSON para obtener imágenes individuales, podemos implementar la lógica de obtener las imágenes en segundo plano a través de controladores o subprocesos o AsyncTask. Debemos tener en cuenta que, dado que mis imágenes una vez descargadas se deben mostrar en la UI / hilo principal, no podemos simplemente usar hilos, ya que no tienen acceso al contexto. En el adaptador de Flickr, las opciones que podría pensar:

  • Opción 1: crear un LooperThread [se extiende el hilo] - y continuar descargando imágenes secuencialmente en un hilo manteniendo este hilo abierto [looper.loop ()]
  • Opción 2: hacer uso de un grupo de subprocesos y publicar el ejecutable a través de myHandler que contiene referencia a mi ImageView, pero como las vistas en la vista de cuadrícula se reciclan, nuevamente el problema puede surgir cuando la imagen en el índice 4 se muestra en el índice 9 [la descarga puede toma mas tiempo]
  • Opción 3 [Utilicé esto]: haga uso de un grupo de subprocesos y envíe un mensaje a myHandler, que contiene datos relacionados con el índice de ImageView y con ImageView mismo, así que mientras hacemos handleMessage () actualizaremos ImageView solo si currentIndex coincide con el índice de La imagen que intentamos descargar.
  • Opción 4: utilice AsyncTask para descargar las imágenes en segundo plano, pero aquí no tendré acceso a la cantidad de subprocesos que deseo en el grupo de subprocesos y varía según la versión de Android, pero en la Opción 3 puedo tomar una decisión consciente del tamaño del conjunto de subprocesos según la configuración del dispositivo que se esté utilizando.

Aquí el código fuente:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Espero que mi respuesta, aunque larga, ayude a comprender algunos de los detalles más finos.


Hilo

Cuando inicia una aplicación, se crea un proceso para ejecutar el código. Para utilizar de manera eficiente los recursos informáticos, se pueden iniciar subprocesos dentro del proceso para que se puedan ejecutar múltiples tareas en ese momento. Por lo tanto, los hilos le permiten crear aplicaciones eficientes utilizando la CPU de manera eficiente sin tiempo de inactividad.

En Android, todos los componentes se ejecutan en un único hilo principal llamado. Las tareas de la cola del sistema Android y las ejecutan una a una en el hilo principal. Cuando se ejecutan tareas de ejecución prolongada, la aplicación deja de responder.

Para evitar esto, puede crear subprocesos de trabajo y ejecutar tareas en segundo plano o de larga ejecución.

Entrenador de animales

Dado que Android utiliza el modelo de un solo subproceso, los componentes de la interfaz de usuario se crean sin hilos, lo que significa que solo el subproceso que creó debe acceder a ellos, lo que significa que el componente de la interfaz de usuario debe actualizarse solo en el subproceso principal. Como el componente de la interfaz de usuario se ejecuta en el hilo principal, las tareas que se ejecutan en las hebras de trabajo no pueden modificar los componentes de la interfaz de usuario. Aquí es donde Handler entra en escena. El manejador con la ayuda de Looper puede conectarse a un nuevo hilo o un hilo existente y ejecutar el código que contiene en el hilo conectado.

El manejador hace posible la comunicación entre subprocesos. Usando Handler, el hilo de fondo puede enviarle resultados y el handler que está conectado al hilo principal puede actualizar los componentes de la interfaz de usuario en el hilo principal.

AsyncTask

AsyncTask provisto por Android usa tanto el hilo como el controlador para facilitar la ejecución de tareas simples en segundo plano y actualizar los resultados del hilo de fondo al hilo principal.

Por favor, vea el hilo de Android, el controlador, asynctask y grupos de hilos para ver ejemplos.







android-handler