¿Cuál es la diferencia entre controlador y servicio en Android?
La mayoría de los componentes y aplicaciones de Android son conceptos estáticos. Cuando se ejecuta una aplicación, es inevitable preocuparse por los conceptos de procesos y subprocesos. En Android, el concepto más distintivo de operación dinámica de componentes es tarea, que debe traducirse en Tarea.
La función más importante de la intervención de tareas es separar las conexiones entre componentes de los detalles del concepto del proceso, y se puede configurar utilizando diferentes modelos. En muchos casos, puede simplificar la comprensión de los desarrolladores de nivel superior y ayudarlos a desarrollar y configurar mejor.
Trabajo
Hay una buena analogía con la Tarea (guía/temas/fundamentos. html # act Tarea) en el SDK, que dice que Tarea es equivalente al concepto de aplicación. A los ojos de los desarrolladores, desarrollar un programa para Android consiste en crear un componente único, pero para los usuarios comunes, lo que perciben es solo una aplicación general en ejecución, y detrás de todo esto hay una tarea.
En pocas palabras, una tarea es un conjunto de componentes activos reunidos en una pila. Pueden estar relacionados entre sí. El componente de actividad recién agregado se encuentra en la parte superior de la pila y solo las actividades en la parte superior de la pila tienen la oportunidad de interactuar con el usuario. Cuando la actividad en la parte superior de la pila completa su tarea, Task la sacará de la pila y dejará que la siguiente actividad que se ejecutará en la parte superior de la pila se enfrente al usuario hasta que no haya más actividades en la pila y la tarea finalice. .
Pila de tareas de eventos
Haz clic en la aplicación de correo electrónico y ve a la bandeja de entrada (actividad a)
Selecciona un correo electrónico y haz clic en el botón de actividad.
Haga clic en Responder para comenzar a redactar un nuevo correo electrónico (Actividad C) ABC.
Escribe unas líneas, haz clic para seleccionar el contacto e introduce la actividad D ABCD.
Selecciona el contacto y continúa escribiendo el correo ABC
Escribe el correo, envíalo y regresa a la dirección de correo original AB.
Haga clic en "Anterior" para regresar a la bandeja de entrada a
Salir del programa de correo electrónico está vacío
Como se muestra en la tabla anterior, es un ejemplo. La pila de tareas cambia a lo largo del proceso desde el momento en que el usuario ingresa al buzón hasta que completa la respuesta y sale de la aplicación. Este es un modelo de pila estándar. Para la mayoría de situaciones, este modelo de tarea es suficiente, pero cuando se trata de rendimiento real, gastos generales, etc., se vuelve mucho más brutal. Por ejemplo, iniciar un navegador en Android es un proceso tedioso que requiere mucho trabajo de inicialización y mucha sobrecarga de memoria. Pero al mismo tiempo, usar un navegador para abrir algún contenido es un requisito para las aplicaciones generales. Imagínese qué escena tan cruel sería si hubiera diez aplicaciones ejecutándose (correspondientes a múltiples tareas) al mismo tiempo y todas necesitaran iniciar el navegador. Diez pilas de tareas repletas de actividad de navegador muy similar son un desperdicio magnífico. Entonces tendrá una idea de si la actividad del navegador puede existir como una tarea separada y la tarea del navegador no se fusionará con el pasado independientemente de la solicitud de esa tarea. De esta manera, aunque la actividad del navegador en sí necesita mantener un mayor estado, el costo general se reducirá considerablemente. Este comportamiento de renunciar a la familia para todos sigue siendo digno de elogio.
Por supuesto, Android admitirá un comportamiento tan encomiable con ambas manos. En Android, el modo de tarea de cada actividad puede ser configurado y seleccionado por el proveedor de la actividad (a través del archivo de configuración...) y el consumidor de la actividad (a través de la información de marca en la intención... Por supuesto, el control del usuario sobre). la actividad sólo está dentro del alcance permitido por el prestador, los usuarios no pueden utilizar modalidades que estén expresamente prohibidas por el prestador.
En el SDK (Guía/Temas/fundamentos. html # act Task), el método de configuración del modo tarea entre ellos está escrito muy claramente. Hablaré de ello brevemente y seleccionaré algunos para explicar (el completo). La versión puede ser Los elementos de configuración deben verse en el SDK, los siguientes son solo algunos elementos comunes...). La configuración de los componentes del proveedor se implementa a través del manifiesto
Para desarrolladores de aplicaciones,
El modo estándar es el modo de misión estándar predeterminado. En ausencia de otros factores, una actividad que utiliza este patrón construye una instancia de la actividad y la agrega a la pila de tareas de la persona que llama. Para actividades con frecuencia de uso promedio y costo promedio, el modo estándar es sin duda el más adecuado. Debido a que su lógica es simple y clara, es la opción predeterminada.
El modo SingleTop, por otro lado, es básicamente el mismo que el estándar, diferenciándose sólo cuando la actividad solicitada está en la parte superior de la pila. En este momento, la actividad configurada como singleTop ya no construirá una nueva instancia y la agregará a la pila de tareas, sino que enviará nuevas intenciones a la actividad en la parte superior de la pila. Nueva intención al sobrecargar a onnewitt (por supuesto, también puede Ignorar...). Este modo reduce cierta sobrecarga de duplicación cuando está en la parte superior de la pila y evita algunos comportamientos extraños (imagínese si varias actividades consecutivas en la parte superior de la pila son las mismas). lo mismo, y luego salir en el primer nivel, Qué experiencia de usuario sería...), perfecto para algunas demostraciones de actividades de listas actualizadas. Un ejemplo vivo es que en la aplicación proporcionada por Android de forma predeterminada, la actividad de marcadores del navegador (BrowserBookmarkPage) usa singleTop.
El modo SingleTop, aunque rompe la lógica de la pila original (reutilizar la parte superior de la pila sin construir nuevos elementos en la pila...), no abre tareas dedicadas. Tanto SingleTask como singleInstance adoptan diferentes métodos de procesamiento de tareas. Hay como máximo una instancia activa denominada singleTask, que se encuentra en la tarea de la que es raíz. Todas las solicitudes para esta actividad saltarán a las tareas de la actividad y se expandirán. SingleTask, al igual que el concepto de patrón singleton, todas las modificaciones se basan en una instancia, generalmente utilizada en actividades con alto costo de construcción pero bajo costo de cambio. Este modo se usa ampliamente en aplicaciones proporcionadas por el código fuente de Android. El ejemplo más típico es la actividad principal de la aplicación del navegador (llamada Navegador...), que es una ventana que muestra la pestaña actual y el contenido de la página actual. Su costo de construcción es alto, pero el cambio de página sigue siendo muy rápido, lo cual es muy adecuado para singleTask.
Por el contrario, singleInstance es más extremo. En la mayoría de los casos, singleInstance es idéntico a singleTask. La única diferencia es que la actividad de singleInstance es la única actividad en su pila. Si se trata de otras actividades, se entregarán a otras tareas. Esto hace que la actividad de singleInstance sea como una isla, completamente una caja negra, sin importar de dónde viene la solicitud ni quién la ejecutará en el futuro. Hay muy poca actividad como esta en las aplicaciones predeterminadas de Android. En mi práctica personal de ingeniería, trato de usarlos en las actividades de recuperación rápida de palabras del Diccionario Youdao, porque creo que la entrada de recuperación rápida de palabras es bastante conveniente (haga clic para ingresar desde la notificación) y se usa en varias ocasiones, por lo que debería ser completamente independiente.
Además de launchMode, que se puede utilizar para tareas de implementación,
Process
En el desarrollo de la mayoría de las otras plataformas, cada desarrollador aplica el modelo de proceso a él mismo Todo el mundo tiene un entendimiento muy claro. Por ejemplo, para un programa de consola, puede imaginar que inicia un proceso desde la función principal, finaliza con la función principal y sale después de que se ejecuta el proceso. En los programas de interfaz de usuario, a menudo se ejecuta un bucle de mensajes; Cuando se reciba un mensaje de salida, salga del bucle de mensajes para finalizar el proceso.
Durante la ejecución del programa, cada desarrollador sabe claramente qué procesos se inician, la comunicación con procesos de terceros, etc. Las fronteras del proceso, aquí, son como fronteras nacionales: cada cruce dejará una profunda huella.
En los programas de Android, lo que los desarrolladores pueden percibir directamente a menudo son sólo tareas. Lo que está claro es el límite de los componentes, mientras que el límite del proceso se vuelve difícil de alcanzar, incluso se menciona el alojamiento del proceso. Android no solo le quita a las personas el poder de falsificar recuerdos con las manos, sino que también monopoliza el poder de manejar procesos con las manos sin dudarlo.
Por supuesto, Android oculta los detalles del proceso, no de forma deliberada, sino de forma natural. Si llamamos desarrollo orientado a procesos de aplicaciones tradicionales, entonces lo que hacemos en Android es desarrollo orientado a componentes. Como se puede observar en el contenido anterior, los saltos y comunicaciones entre componentes de Android se realizan con la participación de un tercero. Debido a este tipo de intervención, los dos componentes generalmente no tienen contacto directo (la comunicación con el Servicio no requiere intervención de terceros, por lo que Android asume que la comunicación se realiza a través de los límites del proceso y se basa en RPC para ocultar los detalles del proceso). .), No importa si se cruza un límite de proceso o no. Entonces, si los desarrolladores necesitan prestar atención al proceso en este momento, se volverá muy extraño y confuso. En pocas palabras, Android alojará todos los procesos juntos y la capa superior no necesita conocer los detalles de vida, muerte y comunicación del proceso.
En la parte inferior de Android, el proceso construye un grupo en ejecución. No solo se alojan los componentes activos de la tarea, sino también los otros tres componentes, servicios, proveedores de contenido y receptores de transmisión. en la parte inferior. Aquí, el proceso es más como un grupo de recursos (el concepto es como un grupo de subprocesos, la capa superior simplemente saca uno cuando es necesario, sin importar cuál...), solo para llevar a cabo las operaciones de cada componente, y lo hacen. No le importa la relación lógica directa de cada componente. Sin embargo, podemos imaginar que para garantizar la integridad, Android definitivamente tenderá a incluir todos los componentes de la misma tarea y aplicación en el mismo proceso de forma predeterminada. Por supuesto, por razones de eficiencia, Android también permite a los desarrolladores realizar la configuración.
En el sistema Android, en general
Además de
Dado que el sistema Android ayuda a los desarrolladores a alojar el proceso, se necesita un conjunto de algoritmos complejos para ejecutar el reciclaje. lógica. La vida y la muerte de cada proceso en Android está estrechamente relacionada con los componentes que se ejecutan en él. Según las características de sus componentes, los procesos se organizan en un sistema de prioridad. Cuando se requiere reciclaje, el reciclaje se realiza de baja prioridad a alta prioridad. Los procesos de Android * * * se dividen en cinco categorías de prioridad, a saber: proceso en primer plano, proceso visible, proceso de servicio, proceso en segundo plano y proceso vacío. Como sugiere el nombre, no es difícil ver que cuanto más estrecha sea la conexión operativa con los usuarios, más interacciones con los usuarios y cuanto mayor sea la prioridad, más difícil será reciclarlo. Para obtener más información, consulte: guía/temas/fundamentos html # proc life.
Con prioridad, también necesitamos una buena oportunidad de reciclaje. El reciclaje prematuro y la baja probabilidad de aciertos en la caché pueden provocar que la creación continua de procesos destruya los procesos, y las ventajas del reciclaje del grupo desaparecerán demasiado tarde, lo que aumentará el costo general y reducirá la eficiencia operativa del sistema; Un buen Ferrari puede convertirse en un coche clásico QQ. Lo más importante para la recuperación de procesos de Android es considerar otros recursos, como el costo de la memoria y la energía. Además, la cantidad de componentes que lleva cada proceso y la cantidad de procesos abiertos por una sola aplicación también son indicadores importantes para la medición. Además, parte del tiempo de ejecución también se controla estrictamente y los procesos que se inician lentamente se eliminarán por la fuerza. Android verificará los parámetros anteriores con regularidad y también intentará reciclar en algunos puntos cuando pueda ocurrir el reciclaje del proceso, como después de ejecutar un componente.
Desde la perspectiva de la experiencia del usuario, el mecanismo de proceso de Android tiene un lado muy gratificante.
Algunos programas se inician muy lentamente, pero si los recursos son abundantes, si los sale y los reutiliza repetidamente, el inicio será extremadamente rápido (el proceso no muere, simplemente pasa del fondo al primer plano), gracias al alojamiento de procesos. Por supuesto, el otro lado está triste. El algoritmo de alojamiento de Android todavía muestra un lado infantil de vez en cuando. Evidentemente, los usuarios han sentido claramente que la velocidad de funcionamiento del sistema operativo se ha ralentizado. Cuando abren el administrador de tareas, ven un montón de aplicaciones todavía vivas y coleando, y tienen que ayudarlos manualmente a terminar con sus vidas y encontrar sus tumbas. Esto hace que el administrador de tareas sea básicamente un software imprescindible para Android.
Desde una perspectiva de desarrollo, el mecanismo de proceso de Android libera las manos y los pies de los desarrolladores. Los desarrolladores no necesitan construir deliberadamente un proceso en segundo plano para monitorear en secreto y en silencio un cierto período de tiempo, tratando de forjar su propio proceso a través de varios métodos de protección como un fénix Ikki. La cuestión de la vida o muerte del proceso se ha planteado dentro del alcance de lo que el desarrollador promedio necesita gestionar. Pero al mismo tiempo, al igual que la disputa entre GC y la gestión de la memoria humana, todos los desarrolladores no creen que el algoritmo pueda ser más eficiente y mejor que ellos mismos. Pero siempre he creído que todas las ventajas de la eficiencia desaparecerán con la mejora continua de los algoritmos y del hardware. Sólo la simplicidad del modelo de desarrollo no cambiará con el tiempo.
Ciclo de vida del componente
Cualquier cambio en la arquitectura conducirá a cambios en el modelo de desarrollo de nivel superior. Aunque el modelo de proceso de Android elimina la necesidad de que los desarrolladores presten mucha atención a los momentos en que se crean y destruyen los procesos, aún deben prestar atención al impacto de estos momentos en los componentes. Por ejemplo, es posible que deba conservar lo que está escrito en la memoria del disco duro antes de que se destruya el proceso, por lo que debe prestar atención a algunos eventos antes de que el proceso finalice.
En Android, para comprender estos puntos temporales, debemos comprender el ciclo de vida de los componentes. El llamado ciclo de vida de un componente significa que cuando un componente cambia entre el primer plano y el fondo, el usuario lo crea y lo sale, y el sistema lo recicla, algunos eventos se notificarán al componente correspondiente y los desarrolladores pueden manejarlo selectivamente en el momento correspondiente. Estos eventos realizan algún trabajo adicional.
A excepción del proveedor de contenido, otros componentes tendrán el concepto de ciclo de vida y todos necesitarán manejar algunas situaciones de manera regular y regular de acuerdo con este modelo. Para ver todo el contenido, consulte: guía/temas/fundamentos html # l ciclos. Aquí atrapamos al ladrón primero, todavía usando la actividad como modo.
Continuar robando imágenes del SDK. Un viaje de vida de actividades naturales, que comienza en la creación y termina en la destrucción. Sin embargo, la luna está creciendo y menguando y sus componentes están en peligro. Cuando el sistema lo necesita, el componente queda en segundo plano y el proceso en el que se encuentra puede sacrificarse por el país y reciclarse en cualquier momento, lo que hace que sea muy importante saber cómo cortar en segundo plano.
Cuando el componente ingresa a la parte superior de la pila e interactúa con el usuario, se llama a la función onResume. De manera similar, al salir de la parte superior de la pila, se llama a la función onPause. OnResume y onPause pueden manejar muchas cosas. Lo más común es leer y escribir algunos archivos o configuraciones. Porque, cuando este componente ya no se ejecuta en primer plano, es posible que otros componentes necesiten leer y escribir los mismos archivos y configuraciones. Si no actualiza el currículum, se pueden usar datos sucios (por supuesto, la situación específica requiere un análisis específico. Si muchas personas no leerán ni escribirán el archivo, se puede colocar en onCreate para realizar el trabajo de lectura).
Además del problema antes mencionado de ser acosado por otros componentes al pasar a segundo plano, la muerte inexplicable también es algo muy aterrador. En Android, hay dos formas comunes en que los componentes mueren. Una es la muerte natural. Por ejemplo, si el elemento de la pila ABC se convierte en AB, el componente C morirá naturalmente. Este método de muerte es tan ligero como una pluma y no requiere cuidados adicionales. Pero en otro caso, fue reciclado por el sistema y volvió a morir como una montaña, sacrificando su vida por el país.
Sin embargo, este método de muerte resulta aún más confuso para los usuarios. Imagínese no poder guardar un juego. Llevas tres días y tres noches jugando sin pegar ojo. En este momento, tu mm te llama para animarte.
Estás lleno de energía y listo para seguir trabajando duro, pero descubres que el sistema recicla tu proceso de juego, después de pasar a un segundo plano. De la noche a la mañana, intentas convertirte en la burbuja que eras tres días antes de la liberación. ¿Te gustaría matar a alguien que juegue este juego? ¿Quieres? En este momento, no existe un ciclo de vida de actividad y el programador del juego debe haber sido perjudicado y convertirse en el chivo expiatorio de Android. Sin embargo, los componentes de Android tienen un ciclo de vida. Si esto sucede, no dudes en matar al desarrollador.
Para escapar, los programadores tienen una medalla de oro para evitar la muerte. Este es el mecanismo de estado de Android. El llamado estado significa que el desarrollador almacena información del estado de ejecución actual en un objeto Bundle. Este objeto Bundle es una colección de pares clave-valor serializables. Si es necesario reciclar el proceso de un componente activo, el kernel de Android persistirá en el disco el objeto Bundle del componente activo que se encuentra encima de él. Cuando el usuario regresa a la actividad, el sistema reconstruye el componente y restaura el objeto del paquete persistido en el disco. Con información de estado tan persistente, los desarrolladores pueden distinguir bien el método específico de muerte y tienen la oportunidad de restaurar la actividad desde el estado muerto al estado anterior a la muerte. Lo que los desarrolladores deben hacer es escribir la información de estado que debe mantenerse (de forma predeterminada, los controles del sistema guardarán ellos mismos la información de estado relevante, como TextView, que guardará la información de texto actual, los desarrolladores no tienen que preocuparse). .) en el objeto Bundle y luego leer y restaurar información relevante en la función onSaveInstanceState (onCreate, onStart, también se pueden procesar...).
Línea
Leer datos. , procesamiento en segundo plano, estos desgraciados muchachos, naturalmente, la participación de hilos es indispensable. En el nivel de programación del núcleo de Android, no se molesta en considerar subprocesos. Solo se centra en el proceso. La construcción y el procesamiento de cada componente se completan en el hilo principal del proceso, lo que puede garantizar que la lógica sea lo suficientemente simple. El multiproceso es a menudo algo que los desarrolladores deben hacer.
Los subprocesos de Android también se implementan derivando objetos de subprocesos de Java e implementando el método Run. Pero cuando los usuarios necesitan ejecutar un hilo con un bucle de mensajes, Android tiene mejor soporte de Handler y Looper. Handler realiza la transmisión y distribución de mensajes y deriva su función handleMessage, que puede manejar varios mensajes recibidos, al igual que Win Development. La tarea de Looper es construir un bucle y esperar a que lleguen la salida u otros mensajes. En la página SDK de Looper, hay un ejemplo estándar de implementación de un hilo de bucle de mensajes. Por supuesto, un enfoque más estándar podría ser construir un hilo HandlerThread y pasar su Looper al controlador.
En Android, el uso de proveedores de contenidos suele estar relacionado con hilos, por lo que está relacionado con datos. Como se mencionó anteriormente, para mantener una mayor flexibilidad, el propio proveedor de contenido solo proporciona una interfaz para llamadas sincrónicas. Dado que la adición, eliminación, modificación y consulta asincrónicas de proveedores de contenido son operaciones comunes, Android las proporciona a través del objeto AsyncQueryHandler. interfaz. Esta es una subclase de Handler. Los desarrolladores pueden llamar al método startXXX para iniciar una operación, derivar el método onXXXComplete y esperar una devolución de llamada después de la ejecución para completar todo el proceso de llamada asincrónica, lo cual es muy simple y claro.
Implementación
El núcleo de toda la gestión de tareas y procesos se implementa en ActivityManagerService. Como se mencionó en el artículo anterior, la resolución de intenciones es responsabilidad de este ActivityManagerService. De hecho, es una clase que no merece su nombre, pues aunque se denomina servicio gestor de actividades, su jurisdicción incluye no sólo las actividades, sino también los otros tres tipos de componentes y sus procesos.
En ActivityManagerService, hay dos estructuras de datos más llamativas, una es ArrayList y la otra es HashMap.
ActivityManagerService tiene una gran cantidad de ArrayLists y cada componente tendrá múltiples ArrayLists almacenados en diferentes estados. El trabajo de programación a menudo se toma de una lista de matriz, se ajusta y luego se coloca en otra lista de matriz. Cuando este componente no tiene un ArrayList correspondiente, significa que la muerte no está muy lejos. HashMap se utiliza porque algunos componentes deben ubicarse por nombre o información de intención, como proveedores de contenido, y su búsqueda se basa en Uri. Con HashMap todo es lógico.
ActivityManagerService utiliza algunas estructuras de datos denominadas xxxRecord para representar los componentes supervivientes. Entonces están HistoryRecord (guarda información de actividad, por eso se llama historial, que es relativo a la pila de tareas...), ServiceRecord, BroadcastRecord, ContentProviderRecord, TaskRecord, ProcessRecord, etc.
Cabe destacar que TaskRecord. Siempre hemos hablado del concepto de pila de tareas, pero de hecho, la capa inferior real no mantiene una pila activa en TaskRecord. En ActivityManagerService, las actividades de cada tarea se almacenan en una ArrayList en forma de HistoryRecord, y cada HistoryRecord almacena una referencia a su TaskRecord. Cuando se ejecuta una actividad y sale de la pila de tareas conceptual, Android se realiza escaneando HistoryRecord en busca del mismo TaskRecord desde la ubicación actual de HistoryRecord. Este tipo de diseño hace que muchos sistemas de tareas con lógica compleja de nivel superior estén unificados y sean simples de implementar, lo cual es encomiable.
ProcessRecord es el núcleo de toda la implementación del alojamiento del proceso. Contiene información sobre todos los componentes que se ejecutan en este proceso. A partir de esta información, el sistema dispone de un conjunto de algoritmos para decidir cómo manejar el proceso. Si está interesado en el algoritmo de reciclaje, puede comenzar con la función trimApplications de ActivityManagerService.
Para los desarrolladores, comprender la implementación de esta parte puede ayudar principalmente a comprender el concepto de todo el proceso y las tareas. Si cree que comprende este aspecto muy claramente, entonces no es necesario que toque el gigante ActivityManagerService.
================
Esta es una copia y se siente mejor que el primer piso.
==============
Es tuyo.
Es necesario configurar el servicio antes de poder utilizarlo.
No hablemos del uso de hilos.
Hanler es una cosa que se usa para colas de mensajes. El controlador se puede usar para actualizar la visualización de controles y comunicarse entre subprocesos.
Un servicio sólo se puede iniciar en segundo plano y es uno de los componentes de la aplicación.