Android Studio por dentro
El IDE como cliente de Gradle: la estructura real del proyecto y sus conjuntos de fuentes, las ventanas que se usan todos los días, y la configuración que separa un entorno fluido de uno que estorba.
Android Studio parece un editor y no lo es. Es un cliente gráfico de tu sistema de construcción: no sabe qué clases existen, ni qué dependencias tienes, ni siquiera cuántos módulos hay, hasta que Gradle se lo cuenta. Entender esa relación —quién es la fuente de verdad y quién el espectador— explica de golpe el noventa por ciento de las rarezas del IDE: por qué el autocompletado desaparece, por qué una clase generada aparece en rojo, y por qué la solución nunca es reiniciar sino sincronizar.
- Entender qué es Android Studio y por qué depende del modelo que produce Gradle.
- Leer la estructura real de un proyecto y sus conjuntos de fuentes.
- Manejar las ventanas que de verdad se usan a diario y descartar el resto.
- Configurar memoria, indexado y atajos para que el entorno deje de estorbar.
Un IntelliJ con un modelo de proyecto prestado
Android Studio es IntelliJ IDEA Community más un conjunto de plugins de Google. Todo lo que hace el editor —resaltado, navegación, refactorización, análisis estático— proviene de un modelo de proyecto que el IDE no inventa: lo pide a Gradle ejecutando la fase de configuración del build. Eso es exactamente lo que ocurre durante un Gradle sync.
flowchart LR A[Editas settings o build.gradle.kts] --> B[Gradle sync] B --> C[Fase de configuracion del build] C --> D[Modelo de proyecto del IDE] D --> E[Indexado y resolucion de simbolos] E --> F[Autocompletado y navegacion y refactor] B --> G[Fallo de sync y el IDE usa un modelo viejo] style D fill:#89b4fa,color:#11111b style G fill:#f38ba8,color:#11111b
El corolario práctico es fuerte: cuando el IDE “no ve” algo que existe, casi nunca es un fallo del editor. Es un modelo desactualizado. Los ficheros que gobiernan ese modelo viven en la raíz y conviene conocerlos uno a uno.
| Fichero | Qué decide |
|---|---|
settings.gradle.kts |
Qué módulos existen y de qué repositorios se resuelven las dependencias |
build.gradle.kts raíz |
Plugins comunes y su versión, sin aplicarlos |
app/build.gradle.kts |
El módulo real: SDK, variantes, dependencias, opciones de compilación |
gradle/libs.versions.toml |
El catálogo de versiones, fuente única para todas las dependencias |
gradle.properties |
Memoria de la JVM, caché, banderas del build compartidas por el equipo |
local.properties |
Ruta del SDK en tu máquina, nunca en el control de versiones |
gradle/wrapper/ |
La versión exacta de Gradle que usa el proyecto, para todo el mundo |
.idea/ |
Ajustes del IDE, en parte compartidos y en parte personales |
Las dos vistas y dónde vive cada cosa
El desplegable superior del panel de proyecto ofrece varias vistas del mismo disco. La vista Android es una ficción útil: agrupa, esconde y reordena para que veas la aplicación. La vista Project muestra el árbol tal cual está en el sistema de ficheros. Trabaja en Android y cambia a Project en cuanto tengas una duda real.
app/
build.gradle.kts
src/
main/ # el conjunto de fuentes por defecto
AndroidManifest.xml # componentes, permisos, metadatos
java/com/ejemplo/app/ # codigo Kotlin, aunque la carpeta se llame java
res/ # recursos compilados: layouts, valores, dibujables
assets/ # ficheros crudos, servidos tal cual
debug/ # solo en la variante de depuracion
release/
test/ # pruebas locales en la JVM
androidTest/ # pruebas instrumentadas, en dispositivo
build/
generated/ # BuildConfig, R, codigo de KSP: leer, nunca editar
outputs/ # apk, aab y mapping de R8
Todo lo que cuelga de build es derivado y desechable: ahí viven la clase R con los identificadores de recursos, BuildConfig con las constantes de la variante y el código que generan los procesadores de anotaciones. Se lee para entender qué produjo el build, jamás se edita, y no se versiona.
La idea que hay que interiorizar es la de conjunto de fuentes. Gradle fusiona main con el conjunto de la variante activa, y lo mismo hace con los recursos y con el manifiesto. Por eso puedes tener una clave de API distinta en debug, o un icono diferente, sin una sola condición en el código. El selector Build Variants, en la barra lateral izquierda, decide cuál de esas fusiones está viendo el IDE en este momento: si editas un fichero de debug con la variante release activa, el editor lo tratará como código muerto.
Las ventanas que de verdad usas
Logcat
La ventana donde vive el diagnóstico. Su lenguaje de consultas moderno acepta package:mine, level:error y tag: combinados, y permite guardar filtros con nombre. Es la primera pestaña que abres y la última que cierras.
App Inspection
Tres inspectores en una ventana sobre un proceso vivo: base de datos con consultas ad hoc sobre Room, tráfico de red con cuerpos y cabeceras, y tareas en segundo plano con el grafo de WorkManager.
Layout Inspector
La jerarquía real que el sistema está pintando, con propiedades y semántica de Compose. Incluye el recuento de recomposiciones, que convierte una intuición sobre rendimiento en un número.
Profiler
CPU, memoria, energía y trazas de sistema. No se usa a diario, pero cuando hace falta no hay sustituto: es la única forma de ver dónde se van los milisegundos de verdad.
La ventana de Logcat merece una nota aparte porque su lenguaje de consultas sustituye a la vieja combinación de menús desplegables, y componerlo bien es la diferencia entre leer diez líneas y leer diez mil.
package:mine level:warn # solo mi aplicacion, avisos y errores
package:com.ejemplo.app tag:Red -message:ping
level:error & age:5m # errores de los ultimos cinco minutos
A esas cuatro añade dos que se ignoran sin motivo. Build Analyzer aparece tras cada compilación y te dice qué tarea consumió el tiempo, qué plugin rompió la caché y qué dependencia fuerza una reconfiguración completa; es la herramienta que convierte “el build va lento” en una lista de causas. Y Running Devices incrusta el emulador dentro del IDE, lo que elimina el vaivén de ventanas que fragmenta la atención. El resto de paneles que vienen abiertos por defecto se pueden cerrar sin remordimiento: la barra de herramientas ideal es la que no tiene nada que no uses.
Configurarlo para que no te estorbe
Un Android Studio recién instalado está afinado para un ordenador imaginario. Dos ficheros arreglan casi todo. El primero, gradle.properties del proyecto, se comparte con el equipo:
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
android.useAndroidX=true
kotlin.incremental=true
El segundo es la memoria del propio IDE, que se edita desde Help y la opción de personalizar las opciones de la máquina virtual. Un valor de -Xmx4096m es razonable en un equipo con dieciséis gigabytes; subirlo más allá de lo que la máquina puede sostener empeora las cosas, porque el recolector de basura empieza a competir con el demonio de Gradle.
Marca como excluidas las carpetas que no aportan símbolos —build, .gradle, artefactos grandes de recursos— con el botón derecho y la opción de marcar el directorio. Cada carpeta indexada que no consultas nunca es tiempo de arranque y de memoria que pagas todos los días.
Los atajos son la otra mitad del rendimiento personal, y basta con cinco para no volver a tocar el ratón durante la mayor parte del día.
| Atajo | Qué hace |
|---|---|
| Doble pulsación de mayúsculas | Buscar cualquier cosa: fichero, clase, símbolo, acción, ajuste |
Alt-Enter |
Acción contextual: importar, crear lo que falta, refactorizar lo obvio |
Ctrl-E o Cmd-E |
Lista de ficheros recientes, la navegación real de una sesión de trabajo |
Shift-F6 |
Renombrar con todas sus referencias, incluidas las de recursos |
Ctrl-Shift-F o Cmd-Shift-F |
Buscar en el proyecto con ámbito y filtro por tipo de fichero |
La carpeta .idea mezcla ajustes compartibles —estilo de código, inspecciones, diccionario— con estado local que cambia solo, como workspace.xml. Versiona los primeros y excluye el resto: es la única forma de que el equipo comparta criterio sin pelearse en cada fusión.
Tres ajustes más marcan una diferencia desproporcionada. Desactiva los plugins que no usas —hay decenas activos por defecto, para lenguajes y sistemas de control de versiones que no tocas—: cada uno registra inspecciones que se ejecutan mientras escribes. Aprende cuatro atajos y olvida el ratón: la búsqueda global de acciones, la búsqueda universal con doble pulsación de mayúsculas, la lista de ficheros recientes y, sobre todo, la acción contextual de corrección rápida, que resuelve importaciones, crea funciones inexistentes y propone la refactorización obvia. Y define plantillas propias para el código que repites, porque escribir a mano lo que ya sabes que vas a escribir es la forma más silenciosa de perder una hora al día.
Hay una asimetría que conviene grabar a fuego: el botón de ejecutar de Android Studio es una comodidad, pero la autoridad es ./gradlew. El IDE muestra errores que Gradle no da, y Gradle da errores que el IDE no muestra. Ocurre porque el análisis del editor es una aproximación incremental construida sobre un modelo cacheado, mientras que la compilación real ejecuta el grafo completo de tareas con procesadores de anotaciones, generación de código y verificación de recursos. Cuando ambos discrepan, la respuesta correcta no es reiniciar el IDE ni invalidar cachés a ciegas: es ejecutar la compilación en un terminal y creerle a ella. Si Gradle compila y el IDE se queja, tienes un modelo desincronizado y basta sincronizar. Si Gradle falla y el IDE no dice nada, tienes un problema de verdad que el editor no puede ver porque no ejecuta procesadores. Esta distinción se vuelve crítica en cuanto entra en juego un servidor de integración continua, donde no hay IDE en absoluto y el único juez es el mismo ./gradlew que puedes invocar tú. La consecuencia cultural es más profunda de lo que parece: cualquier configuración que solo exista en .idea —una variable de entorno de una configuración de ejecución, una opción marcada en un diálogo— es un secreto que tu equipo no comparte y que tu servidor de construcción no tiene. Todo lo que importe debe vivir en ficheros de build versionados. El IDE es una lente sobre el proyecto, nunca su definición.
- Abre cualquier proyecto y recorre la vista
Projectcompleta: identifica cada uno de los ocho ficheros de la tabla y explica en una frase qué decide cada uno. - Crea una carpeta
src/debug/res/values/strings.xmlque redefina el nombre de la aplicación, cambia la variante activa y observa la fusión en acción. - Rompe el modelo a propósito: añade una dependencia al catálogo de versiones sin sincronizar, comprueba que el editor la marca en rojo, y arréglalo con una sincronización.
- Compila desde el terminal con
./gradlew assembleDebugy compara la salida con la deBuild Analyzer. Localiza la tarea más costosa. - Excluye
builddel indexado, desactiva cinco plugins que no uses y mide el tiempo de arranque antes y después. - Define una plantilla propia para el fragmento que más repites y úsala durante una semana sin excepción.