Mostrando entradas con la etiqueta guía de componentes de aplicación. Mostrar todas las entradas
Mostrando entradas con la etiqueta guía de componentes de aplicación. Mostrar todas las entradas

martes, 14 de octubre de 2014

Procesos y hebras

Cuando una aplicación se ejecuta por primera vez, a través de alguno de sus componentes, el sistema creará para ella un proceso y un flujo de ejecución principal. Por defecto, todos los componentes de una aplicación se ejecutan en el mismo proceso y hebra principal. Sin embargo, si ello fuera necesario, podremos ejecutar los componentes de nuestra aplicación en procesos distintos y dentro de estos, crear las hebras secundarias que consideremos oportunas.

Procesos.

Por defecto, todos los componentes de una aplicación se ejecutan dentro del mismo proceso. Este comportamiento será suficiente para la mayoría de las aplicaciones. No obstante, si necesitamos cambiar este funcionamiento, podremos hacerlo desde el archivo manifest.

Todos los elementos asociados a componentes del archivo manifest: <activity>, <service>, <receiver> y <provider>, soportan el atributo android:process. A través de este atributo podremos especificar el proceso en el que queremos que sea ejecutado el componente. Incluso podríamos utilizar el mismo proceso para componentes de aplicaciones diferentes. Para este último caso, las aplicaciones deberán ejecutarse con el mismo usuario y estar firmadas con el mismo certificado.

El elemento <application> también cuenta con el atributo android:process que podríamos usar para definir el proceso por defecto para todos los componentes de una aplicación.

Hay momentos en los que el sistema se verá obligado a detener ciertos procesos para obtener los recursos requeridos por procesos con mayor prioridad. Cuando un proceso es eliminado por el sistema, todos sus componentes de aplicación serán destruidos.

A la hora de eliminar procesos, el sistema sopesa la importancia de éstos de cara al usuario. Por ejemplo, procesos con actividades que llevan un tiempo considerable siendo no visibles, tendrán un menor peso que aquellos procesos cuyas actividades sean visibles. La decisión de cuándo eliminar un proceso viene determinada por el estado de sus componentes.

miércoles, 24 de septiembre de 2014

Servicios, conceptos básicos

Un servicio es un componente de aplicación que ejecuta de manera indefinida operaciones en segundo plano y por tanto no necesita de una interfaz de usuario. Un servicio puede ser iniciado desde otro componente y seguir ejecutándose independientemente del estado del componente que lo inició. Además, un componente podrá conectarse a un servicio e interactuar con él a través de una interfaz (IPC - Inter Process Communication, Comunicación Entre Procesos). Por ejemplo, un servicio podría encargarse de gestionar las transacciones de red, de reproducir música, de realizar operaciones de entrada y salida (E/S), o de interactuar con un proveedor de contenido; todo ello desde un segundo plano.

sábado, 20 de septiembre de 2014

Ciclo de vida de las actividades.

Cuando interactuamos con una aplicación, sus actividades cambian de estado continuamente. Por ejemplo, cuando una actividad se inicia por primera vez, ésta pasa a un primer plano para interactuar con el usuario. Durante este proceso, Android invoca una secuencia de métodos retrollamada asociados al ciclo de vida de la actividad.  Desde estos métodos, por ejemplo, podremos configurar la interfaz del usuario. Si el usuario realiza alguna acción pasando a iniciar otra actividad, o bien cambia de aplicación, será ésta última la que pase a un primer plano. La actividad inicial pasará a un segundo plano conservándose su estado.

Los métodos retrollamada relacionados con el ciclo de vida de una actividad nos serán útiles para especificar el comportamiento de ésta ante las idas y venidas del usuario. Por ejemplo, si estamos programando un reproductor para vídeo streaming, deberíamos detener la reproducción y cerrar la conexión de red cuando el usuario cambia de aplicación. Si el usuario decide volver al reproductor, volveremos a reestablecer la conexión de red y la reproducción justo donde se había quedado.

Cargadores

Los cargadores hicieron su primera aparición con la versión 3.0 de Android. El objetivo de un cargador es el de facilitar la carga y actualización de los datos usados en una actividad o fragmento. Entre sus características, podemos destacar:
  • Pueden ser usados desde las actividades y fragmentos de nuestra aplicación.
  • La carga de los datos puede realizarse de manera asíncrona.
  • Detectan cambios en la fuente de datos y entregan los nuevos resultados.
  • Si la configuración del dispositivo cambia, el cargador recuperará los datos de la última consulta sin tener que volver a repetirla, con el consiguiente ahorro de tráfico y procesamiento de datos.

miércoles, 17 de septiembre de 2014

Proveedores de contenido, conceptos básicos

Los proveedores de contenido son objetos encargados de gestionar el acceso a un conjunto de datos estructurados. Encapsulan los datos y nos proveen de mecanismos para definir su seguridad. Los proveedores de contenido definen una interfaz estándar que permite a un proceso compartir sus datos con otros procesos.

Cuando queremos acceder a los datos de un proveedor de contenido, utilizaremos el objeto ContentResolver asociado al contexto de nuestra aplicación para comunicarnos como cliente del proveedor. Es decir, utilizaremos el objeto ContentResolver para comunicarnos con un objeto ContentProvider. El objeto proveedor recibe las peticiones de datos desde uno o varios clientes, realiza las acciones solicitadas y devuelve los resultados.

Si los datos de nuestra aplicación no se van a compartir con otras aplicaciones, no tendremos que implementar nuestro propio proveedor. Sin embargo, necesitaremos desarrollar un proveedor para nuestra aplicación si queremos implementar mecanismos de búsqueda con predicción de texto. También necesitaremos de proveedores si queremos que se puedan copiar y pegar datos estructurados o archivos desde nuestra aplicación a otras aplicaciones.

Android incorpora una serie de proveedores de contenido para audio, vídeo, imágenes y contactos. Con algunas restricciones, estos proveedores serán accesibles desde cualquier aplicación.

domingo, 14 de septiembre de 2014

Tareas y la pila de retroceso

Una aplicación suele estar formada por varias actividades. Cada actividad debe ser diseñada en torno a un tipo determinado de acción que el usuario puede realizar y que a su vez puede iniciar otras actividades. Por ejemplo, una aplicación de correo electrónico puede tener una actividad que muestre un listado con los mensajes entrantes y cuando el usuario selecciona uno, se inicia una nueva actividad para mostrar sus detalles.

Una actividad incluso puede iniciar actividades de otras aplicaciones. Por ejemplo, si queremos enviar un correo electrónico, podemos definir una intención para realizar una acción del tipo "send" y añadirle datos adicionales como la dirección del destinatario y el mensaje. Una actividad definida en alguna aplicación y que haya sido declarada para gestionar intenciones del tipo "send", será la encargada de enviar el correo (en el caso de que existan varias actividades en el sistema capaces de responder a la misma intención, el usuario podrá seleccionar qué actividad quiere usar). Una vez se ha enviado el correo, la actividad inicial se reanuda. Todo este proceso es transparente de cara al usuario que en todo momento cree estar en la misma aplicación. Para conseguir esto, Android gestiona ambas actividades dentro de la misma tarea.

viernes, 12 de septiembre de 2014

Fragmentos

Una fragmento es un objeto de tipo Fragment que aporta su propia lógica y aspecto (IU) a una actividad. Una actividad puede contener más de un fragmento y éstos podrán ser reutilizados en varias actividades. Podemos pensar en los fragmentos como en los módulos de una actividad que cuentan con su propio ciclo de vida y que pueden ser añadidos y eliminados de una actividad mientras ésta se esté ejecutando.

Un fragmento siempre estará contenido en una actividad y su ciclo de vida dependerá del ciclo de vida de ésta. Por ejemplo, cuando una actividad entra en pausa, todos sus fragmentos también entrarán en pausa, y cuando una actividad es destruida, todos sus fragmentos también serán destruidos. Sin embargo, mientras una actividad se está ejecutando (es decir, se encuentra en estado reanudada), el estado de cada fragmento funcionará de manera independiente. Además, podremos añadir, eliminar o reemplazar fragmentos a nuestro antojo a través de un mecanismo basado en transacciones. Cada transacción, antes de ser confirmada, podrá ser registrada en una pila de retroceso para fragmentos que gestiona la propia actividad y que permitirá al usuario volver a estados previos con tan solo pulsar el botón de retroceso.

Como norma general, cuando añadimos un fragmento a una actividad, lo que estamos haciendo es insertando su plantilla dentro de la plantilla de la actividad. Podemos insertar un fragmento en una actividad de dos formas: de manera estática, añadiendo un elemento <fragment> a la plantilla de la actividad, o de manera dinámica, añadiendo el fragmento desde el código a una vista contenedora (ViewGroup) previamente instanciada. Sin embargo, no todos los fragmentos cuentan con una plantilla y su objetivo principal consistirá en aportar funcionalidad adicional a una actividad.

lunes, 8 de septiembre de 2014

Actividades

Una actividad es un componente de aplicación que proporciona una pantalla con la que el usuario puede interactuar con el fin de realizar alguna operación, como por ejemplo: hacer una llamada telefónica, hacer una fotografía, enviar un correo electrónico, o ver un mapa. Cada actividad está delimitada por su ventana en la que se muestra la interfaz de usuario. La ventana generalmente ocupa toda la pantalla, pero puede ser más pequeña y flotar sobre otras ventanas.

Una aplicación generalmente está formada por un conjunto de actividades relacionadas entre sí. Una, y solo una, de esas actividades la declararemos como la actividad principal de nuestra aplicación y eso hará que se inicie por defecto cuando el usuario ejecute la aplicación por primera vez.

Una actividad también puede ser iniciada a través de otra actividad con el fin de realizar diferentes acciones. Cuando iniciamos una actividad, ésta se añade a la pila de retroceso (back stack) y pasa a un primer plano, disponible para la interacción con el usuario. Cuando el usuario pulsa el botón de retroceso, la actividad actual se saca del tope de la pila y se destruye, reanudándose la actividad previa. Al sistema de funcionamiento de la pila de retroceso se le conoce por las siglas LIFO (Last In First Out - Último Entra, Primero Sale).

Los cambios de estado que sufre una actividad son comunicados por el sistema mediante la invocación de métodos retrollamada (callbacks) asociados a la propia actividad. Hay varios métodos retrollamada que una actividad puede recibir cuando ésta cambia de estado: cuando el sistema la crea, la detiene, la reanuda, o la destruye. Para cada uno de estos eventos, podremos realizar las operaciones que consideremos necesarias implementando su método correspondiente. Por ejemplo, cuando la actividad es detenida, deberíamos implementar lo necesario para liberar la memoria de objetos pesados, tales como conexiones de red o conexiones a bases de datos. Cuando la actividad se reanuda, recuperaremos los recursos necesarios y continuamos por donde lo habíamos dejado.

viernes, 5 de septiembre de 2014

Intenciones y filtros de intenciones

Una intención (Intent) es un objeto que utilizaremos para iniciar un componente desde otro componente. Aunque las intenciones facilitan la comunicación entre componentes de varias maneras, hay tres casos de uso fundamentales:

  • Para iniciar una actividad (Activity). Una actividad representa una pantalla de nuestra aplicación. Podemos iniciar una actividad pasando una intención como parámetro del método startActivity(). La intención describe qué actividad iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si además queremos recibir algún tipo de resultado desde la actividad cuando ésta finaliza, utilizaremos el método startActivityForResult(). La actividad que originó la solicitud, recibirá el resultado a través de una intención a la que podremos acceder desde su evento onActivityResult().

  • Para iniciar un servicio (Service). Un servicio es un componente que realiza operaciones en segundo plano y que no cuenta con una interfaz de usuario. Puedes iniciar un servicio para realizar una operación (descargar un archivo, por ejemplo) pasando una intención como parámetro al método startService(). La intención describe el servicio a iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si el servicio cuenta con una interfaz cliente-servidor, podrás enlazar el servicio desde un componente pasando una intención como parámetro del método bindService().

  • Para la entrega de avisos (BroadcastReceiver). Un aviso es un mensaje que cualquier aplicación podrá recibir y que se genera como consecuencia de un evento concreto. El sistema avisa de ciertos eventos tales como que el sistema está arrancando, o que se ha iniciado la carga de batería. Podremos enviar avisos a otras aplicaciones pasando una intención como parámetro de los métodos sendBroadcast(), sendOrderedBroadcast(), o sendStickyBroadCast().