En esta guía, se incluyen las prácticas y la arquitectura recomendadas para desarrollar apps sólidas y de calidad.
Experiencias del usuario de apps para dispositivos móviles
Una app de Android típica consta de varios componentes de la app, como actividades, fragmentos, servicios, proveedores de contenido y receptores de emisión. A la mayoría de estos componentes los declaras en el manifiesto de la app. Luego, el SO Android usa ese archivo para decidir la integración de tu app a la experiencia del usuario general del dispositivo. Dado que una app para Android típica puede contener varios componentes y que los usuarios suelen interactuar con diferentes apps en poco tiempo, las apps deben adaptarse a distintos tipos de tareas y flujos de trabajo controlados por los usuarios.
Ten en cuenta que los dispositivos móviles tienen restricciones de recursos, de manera que, en cualquier momento, el sistema operativo podría cerrar algunos procesos de apps para hacer lugar para otros.
Según las condiciones de este entorno, es posible que los componentes de tu app se inicien de manera individual y desordenada, además de que el usuario o el sistema operativo podrían destruirlos en cualquier momento Debido a que no puedes controlar estos eventos, no debes almacenar ni mantener en la memoria ningún estado ni datos de la aplicación en los componentes de tu app, y estos elementos no deben ser interdependientes.
Principios comunes de arquitectura
Si se supone que no deberías usar los componentes de la aplicación para almacenar datos y estados, ¿cómo deberías diseñarla?
A medida que crece el tamaño de las apps para Android, es importante definir una arquitectura que permita que esta crezca, aumente su solidez y facilite su prueba.
La arquitectura de una app define los límites entre sus partes y las responsabilidades que debe tener cada una. A fin de satisfacer las necesidades que se mencionaron antes, debes diseñar la arquitectura de tu app para que cumpla con algunos principios específicos.
Separación de problemas
El principio más importante que debes seguir es el de separación de problemas.
Un error común es escribir todo tu código en una Activity
o un Fragment
. Estas clases basadas en IU solo deberían contener lógica que se ocupe de interacciones del sistema operativo y de IU. Si mantienes estas clases tan limpias como sea posible, puedes evitar muchos problemas relacionados con el ciclo de vida de los componentes y mejorar la capacidad de prueba de estas clases.
Ten en cuenta que las implementaciones de Activity
y Fragment
no son de tu propiedad, sino que estas solo son clases que representan el contrato entre el SO Android y tu app. El SO puede destruirlas en cualquier momento en función de las interacciones de usuarios y otras condiciones del sistema, como memoria insuficiente. Para brindar una experiencia del usuario satisfactoria y una experiencia de mantenimiento de apps más fácil de administrar, recomendamos que dependas en menor medida de esas apps.
Cómo controlar la IU a partir de modelos de datos
Otro principio importante es que debes controlar la IU a partir de modelos de datos, preferentemente que sean de persistencia. Los modelos de datos representan los datos de una app. Son independientes de los elementos de la IU y otros componentes de la app. Por lo tanto, no están vinculados a la IU ni al ciclo de vida de esos componentes, pero se destruirán cuando el SO decida quitar el proceso de la app de la memoria.
Los modelos de persistencia son ideales por los siguientes motivos:
Tus usuarios no perderán datos si el SO Android destruye tu app para liberar recursos.
Tu app continúa funcionando cuando una conexión de red es débil o no está disponible.
Si basas la arquitectura de tu app en clases de modelos de datos, mejorarás la capacidad de prueba y la solidez de tu app.
Única fuente de información
Cuando se define un nuevo tipo de datos en tu app, debes asignarle una Única fuente de información (SSOT, por sus siglas en inglés). La SSOT es la propietaria de esos datos, y solo SSOT puede modificarlos o mutarlos. Con ese fin, la SSOT expone los datos con un tipo inmutable y, para modificarlos, expone funciones o recibe eventos a los que otros tipos pueden llamar.
Este patrón trae varios beneficios:
- Centraliza todos los cambios en un tipo particular de datos en un solo lugar.
- Protege los datos para que otros tipos no puedan manipularlos.
- Hace que los cambios en los datos sean más rastreables. Por lo tanto, los errores son más fáciles de detectar.
En una aplicación que prioriza la condición sin conexión, la fuente de información de los datos de aplicación suele ser una base de datos. En otros casos, la fuente de información puede ser un ViewModel o incluso la IU.
Flujo de datos unidireccional
El principio de fuente de confianza única se suele usar en nuestras guías con el patrón de flujo de datos unidireccional (UDF). En este flujo, el estado fluye en una sola dirección. Los eventos que modifican los datos fluyen en la dirección opuesta.
En Android, el estado o los datos suelen fluir desde los tipos de jerarquía más altos a los de menor alcance. Por lo general, los eventos se activan desde los tipos de alcance inferior hasta que alcanzan la SSOT para el tipo de datos correspondiente. Por ejemplo, los datos de la aplicación generalmente fluyen desde las fuentes de datos hacia la IU. Los eventos del usuario, como presionar el botón, fluyen desde la IU hasta el SSOT, en donde los datos de la aplicación se modifican y se exponen en un tipo inmutable.
Este patrón garantiza mejor la coherencia de los datos, es menos propenso a errores, es más fácil de depurar y brinda todos los beneficios del patrón de SSOT.
Arquitectura de app recomendada
En esta sección, se muestra cómo estructurar la app según las prácticas recomendadas.
Teniendo en cuenta los principios de arquitectura comunes que se mencionaron en la sección anterior, cada aplicación debe tener al menos dos capas:
- La capa de la IU que muestra los datos de la aplicación en la pantalla.
- La capa de datos que contiene la lógica empresarial de tu aplicación y expone sus datos.
Puedes agregar una capa adicional llamada capa de dominio para simplificar y volver a utilizar las interacciones entre la IU y las capas de datos.

Arquitectura moderna de apps
Esta arquitectura moderna de apps promueve el uso de las siguientes técnicas, entre otras:
- Arquitectura en capas y reactiva
- Flujo unidireccional de datos (UDF) en todas las capas de la app
- Una capa de IU con contenedores de estado para administrar la complejidad de la IU
- Corrutinas y flujos
- Prácticas recomendadas para la inserción de dependencias
Para obtener más información, consulta las siguientes secciones, las otras páginas de la arquitectura en el índice y la página de recomendaciones que contiene un resumen de las prácticas recomendadas más importantes.
Capa de la IU
La función de la capa de la IU (o capa de presentación) consiste en mostrar los datos de la aplicación en la pantalla. Cuando los datos cambian, ya sea debido a la interacción del usuario (como cuando presiona un botón) o una entrada externa (como una respuesta de red), la IU debe actualizarse para reflejar los cambios.
La capa de la IU consta de los siguientes dos elementos:
- Elementos de la IU que renderizan los datos en la pantalla (puedes compilar estos elementos con las vistas o las funciones de Jetpack Compose)
- Contenedores de estados (como las clases ViewModel) que retienen datos, los exponen a la IU y controlan la lógica

Para obtener más información sobre esta capa, consulta la página sobre la capa de la IU.
Capa de datos
La capa de datos de una app contiene la lógica empresarial. Esta lógica es lo que le da valor a tu app. Además, está compuesta por reglas que determinan cómo tu app crea, almacena y cambia datos.
La capa de datos está formada por repositorios que pueden contener de cero a muchas fuentes de datos. Debes crear una clase de repositorio para cada tipo de datos diferente que administres en tu app. Por ejemplo, puedes crear una clase MoviesRepository
para datos relacionados con películas o una clase PaymentsRepository
para datos relacionados con pagos.

Las clases de repositorio son responsables de las siguientes tareas:
- Exponer datos al resto de la app
- Centralizar los cambios en los datos
- Resolver conflictos entre múltiples fuentes de datos
- Abstraer fuentes de datos del resto de la app
- Contener la lógica empresarial
Cada clase de fuente de datos debe tener la responsabilidad de trabajar con una sola fuente de datos, que puede ser un archivo, una fuente de red o una base de datos local. Las clases de fuente de datos son el puente entre la aplicación y el sistema para las operaciones de datos.
Para obtener más información sobre esta capa, consulta la página sobre la capa de datos.
Capa de dominio
La capa de dominio es una capa opcional que se ubica entre la capa de la IU y la de datos.
La capa de dominio es responsable de encapsular la lógica empresarial compleja o la lógica empresarial simple que varios ViewModels reutilizan. Esta capa es opcional porque no todas las apps tendrán estos requisitos. Solo debes usarla cuando sea necesario; por ejemplo, para administrar la complejidad o favorecer la reutilización.

Las clases de esta capa se denominan casos de uso o interactores. Cada caso de uso debe tener responsabilidad sobre una funcionalidad única. Por ejemplo, tu app podría tener una clase GetTimeZoneUseCase
si varios ViewModels dependen de las zonas horarias para mostrar el mensaje adecuado en la pantalla.
Para obtener más información sobre esta capa, consulta la página sobre la capa del dominio.
Cómo administrar dependencias entre componentes
Las clases de tu app dependen de otras para funcionar correctamente. Puedes usar cualquiera de los siguientes patrones de diseño para recopilar las dependencias de una clase en particular:
- Inserción de dependencia (DI): Permite que las clases definan sus dependencias sin construirlas. En el tiempo de ejecución, otra clase es responsable de proporcionar estas dependencias.
- Localizador de servicios: Su patrón brinda un registro en el que las clases pueden obtener sus dependencias en lugar de construirlas.
Estos patrones te permiten hacer un escalamiento del código, ya que proporcionan patrones claros para administrar dependencias sin duplicar el código ni aumentar la complejidad. Además, te permiten cambiar rápidamente entre las implementaciones de prueba y de producción.
Te recomendamos seguir los patrones de inserción de dependencia y usar la biblioteca Hilt en las apps para Android. Hilt construye automáticamente objetos con un recorrido del árbol de dependencias, proporciona garantías de tiempo de compilación sobre dependencias y crea contenedores de dependencias para clases de framework de Android.
Prácticas recomendadas generales
La programación es una disciplina creativa y crear apps de Android no es una excepción. Hay muchas maneras de resolver un problema: puedes comunicar datos entre varias actividades o fragmentos, recuperar datos remotos y conservarlos a nivel local para el modo sin conexión, o bien controlar cualquier cantidad de situaciones comunes con las que pueden encontrarse las apps no triviales.
Aunque las siguientes recomendaciones no son obligatorias, en la mayoría de los casos, si las sigues, tu código base será más confiable, tendrá mayor capacidad de prueba y será más fácil de mantener a largo plazo.
No almacenes datos en los componentes de la app
Evita designar los puntos de entrada de tu app (receptores de emisiones, servicios y actividades) como fuentes de datos. En cambio, solo deben coordinar con otros componentes para recuperar el subconjunto de datos relevante para ese punto de entrada. Cada componente de la app tiene una duración relativamente corta, según la interacción que el usuario tenga con su dispositivo y el estado general del sistema en ese momento.
Reduce las dependencias de clases de Android
Los componentes de tu app deben ser las únicas clases que dependan de las APIs del SDK del framework de Android, como Context
o Toast
. La abstracción de otras clases en tu app fuera de ellas ayuda con la capacidad de prueba y reduce el acoplamiento dentro de la app.
Crea límites de responsabilidad bien definidos entre varios módulos de tu app.
Por ejemplo, no extiendas el código que carga datos de la red entre varias clases o paquetes en tu código base. Del mismo modo, no definas varias responsabilidades no relacionadas, como caché de datos y vinculación de datos, en la misma clase. Podría ser útil que siguieras la arquitectura de la app recomendada.
Expón lo mínimo indispensable de cada módulo
Por ejemplo, no caigas en la tentación de crear un acceso directo que exponga un detalle interno de la implementación de un módulo. Quizás ahorres algo de tiempo a corto plazo, pero tendrás más probabilidades de que se generen problemas técnicos a medida que tu código base evolucione.
Concéntrate en aquello que hace única a tu app para que se destaque del resto
No desperdicies tu tiempo reinventando algo que ya existe ni escribiendo el mismo código estándar una y otra vez. En cambio, enfoca tu tiempo y tu energía en aquello que hace que tu app sea única y deja que tanto las bibliotecas de Jetpack como las otras recomendadas se ocupen del código estándar repetitivo.
Piensa en cómo lograr que cada parte de tu app se pueda probar por separado
Por ejemplo, una API bien definida para recuperar datos de la red facilitará las pruebas que realices en el módulo que conserve esa información en la base de datos local. En cambio, si combinas la lógica de estos dos módulos en un solo lugar, o bien si distribuyes el código de red por todo tu código base, será mucho más difícil (y quizás hasta imposible) ponerlo a prueba eficazmente.
Los tipos son responsables de su política de simultaneidad
Si un tipo realiza un trabajo de bloqueo de larga duración, debería ser responsable de mover ese cálculo al subproceso correcto. Ese tipo particular conoce el tipo de procesamiento que está haciendo y en qué subproceso debe ejecutarse. Los tipos deben ser seguros para el subproceso principal, lo que significa que son seguros llamarlos desde el subproceso principal sin bloquearlo.
Conserva la mayor cantidad posible de datos relevantes y actualizados
De esa manera, los usuarios podrán aprovechar la funcionalidad de tu app, incluso cuando su dispositivo esté en modo sin conexión. Recuerda que no todos tus usuarios cuentan con una conexión de alta velocidad de manera constante y, si lo hacen, pueden tener una mala recepción en lugares muy concurridos.
Beneficios de la arquitectura
Tener una buena arquitectura implementada en tu app trae muchos beneficios a los equipos de proyectos y de ingeniería:
- Mejora la capacidad de mantenimiento, calidad y solidez de la app en general.
- Permite que la aplicación escale. Más personas y más equipos pueden contribuir a la misma base de código con conflictos de código mínimos.
- Ayuda con la integración. A medida que la arquitectura aporta coherencia a tu proyecto, los miembros nuevos del equipo pueden ponerse al día rápidamente y ser más eficientes en menos tiempo.
- Es más fácil probarlo. Una buena arquitectura fomenta tipos más simples que, en general, son más fáciles de probar.
- Los errores se pueden investigar metódicamente con procesos bien definidos.
Invertir en arquitectura también tiene un impacto directo en tus usuarios, ya que se beneficiarán de una aplicación más estable y de más funciones gracias a un equipo de ingeniería más productivo. Sin embargo, la arquitectura también requiere una inversión de tiempo inicial. Para ayudarte a justificar este tiempo al resto de tu empresa, revisa estos casos de éxito en los que otras empresas comparten sus historias de éxito cuando tienen una buena arquitectura en su app.
Ejemplos
En los siguientes ejemplos de Google, se demuestra una buena arquitectura de la app. Explóralos para ver esta guía en práctica:
Microsoft permite a las personas y organizaciones trabajar, aprender, organizar, conectarse y crear con sus apps líderes de Microsoft 365. Para lograrlo, saben que es fundamental brindar una experiencia de productividad óptima a sus clientes, en todos los dispositivos que usan. Twitter es una de las plataformas de redes sociales más usadas en las que los usuarios pueden ver qué sucede en el mundo en cualquier momento. El equipo de ingeniería comenzó a usar Jetpack Compose para modernizar su
un sistema de diseño eficaz. Como Square ayuda a millones de vendedores a ejecutar su
comerciales: desde el procesamiento seguro de tarjetas de crédito hasta las soluciones de puntos de venta y
la configuración de una tienda en línea gratuita. Square lleva un tiempo migrando a la IU Monzo es un banco y una oferta de apps.
servicios financieros digitales. Su misión es llevar dinero a todo el mundo. El sistema de diseño de Monzo comenzó a desviarse de Material Design, por lo que querían una forma fácil de escribir y mantener Cuvva está mejorando muchísimo los seguros
ya que te brinda una forma muy flexible de administrar tu cubierta, todo desde tu teléfono.
Los ingenieros de Cuvva de Android dedicaron algo de tiempo a rediseñar su app.
y decidiste adoptar un flujo ShareChat is a leading social media platform in India that allows users to share their opinions, document their lives, and make new friends in their native language. The standard Red Up Green Down color scheme that many wealth management app users take for granted can be very problematic for colorblind users and those with color vision deficiency.The Futubull team is embracing users’ needs by making concrete improvements so that everyone can grasp the key to wealth. TikTok, the world’s community-driven entertainment destination, brings over 1 billion people together from around the world to discover, create and share content they love. OkCredit is a credit account management app for millions of shop owners and their customers in India. With 140M transactions month over month, and 50M+ downloads, last year alone saw OkCredit recording $50 billion worth of transactions on the app. Operating at such a huge scale scale, OkCredit created a smooth and seamless experience for all their users by focusing on reducing ANRs and improving the app startup time. Lyft is committed to app excellence. They have to be. For a rideshare app — providing a vital, time-sensitive service to millions of drivers and riders every day — a slow or unresponsive app adds unacceptable friction. Josh is a short-video app from India, launched in 2020. One of the fastest growing short-video apps with over 124 million MAUs, optimizing it across a range of devices (high, mid, low end) and maintaining a standard experience across all of them is critical for their success. Improving app startups time and making the app responsive helped them achieve success. Microsoft Lens increases developer productivity using CameraX Zomato is an Indian multinational restaurant aggregator and food delivery company serving customers across 500 cities in India alone. In order to launch new features on their Android app, Headspace spent 8 months refactoring their architecture and rewriting in Kotlin. Learn how this reboot helped their business grow. Google Photos is the home for your memories, and their development team believes people should be able to enjoy those memories across all devices. Learn how Duolingo made the business decision to focus on Android performance and how they improved developer productivity and scaled their business. Mercari allows millions of people to shop and sell almost anything. The company was founded in 2013 in Japan, and it now is the largest smartphone-focused C2C marketplace in Japan. Google Duo is a simple, high quality video calling app for everyone. With the increase of people being at home during the Covid-19 pandemic, the Duo team saw a significant increase in people using the app to stay connected with friends & family, school and work. Headspace drive business growth by investing in Android app quality. SmartNews helps millions of people discover their world everyday by sharing timely news from a diverse set of news sources. Twitter is one of the most widely used social media platforms where users can see what’s happening in the world at any given moment. Delight Room Alarmy is an alarm app that can be turned off only when the pre-selected activities, such as taking a photo, solving a math problem, shaking phone, etc., are performed by the user. The Google Home app helps set up, manage, and control your Google Home, Google Nest, and Chromecast devices—plus thousands of connected home products like lights, cameras, thermostats, and more. Truecaller is an app that offers caller identification, call blocking, chat messaging and organized inbox. The app has a basic offering and a premium version which is ad-free and has a variety of unlocked features like advanced spam blocking and call recording.Microsoft Outlook, Teams y Office aumentaron los usuarios activos y la retención con pantallas grandes
Twitter aumenta la eficiencia y velocidad de los desarrolladores con Compose
Square aumenta su productividad con Compose
Monzo compila una app más sólida y de mayor calidad con Compose
Cuvva compila más rápido y con mayor calidad con Compose
ShareChat addresses Jank issues to increase feed scrolling by 60%
The Key to Wealth for Everyone
TikTok Optimizes User Experience with Android Tools
OkCredit’s average merchant transaction goes up by 30% after reducing ANR
Lyft improves Android app startup time for drivers by 21%
Josh sees increased customer retention by improving app startup time by 30%
Microsoft Lens increases developer productivity using CameraX
Increasing app speed by 30%: a key ingredient in Zomato’s growth recipe
Headspace's Android reboot increases monthly active users by 15%
Google Photos increased daily active users by building for large screens
Duolingo refactors on Android with MVVM and Jetpack libraries
Mercari improves UI development productivity by 56% with Jetpack Compose
Google Duo sees increased engagement and improved ratings by optimizing for larger screens
Headspace drive business growth by investing in Android app quality
SmartNews reduces lines of code by 20% and improves team morale with Kotlin
Twitter increases developer productivity and code reliability with Kotlin
Delight Room increased 90% of its organic US users with Play Console
Google Home reduces #1 cause of crashes by 33%
Truecaller brings ~40% subscribers back with real time developer notifications
En estos momentos, no hay ninguna recomendación.
Prueba a iniciar sesión en tu cuenta de Google.