Micro optimizaciones 2 - haroldVirguez/VINYLS-MOBILE GitHub Wiki
Ajustes en uso de FrameLayout
Se eliminó un contenedor FrameLayout (envoltorio) innecesario y se dejó ScrollView como root (o se redujo una capa de layout redundante). Esto simplifica la jerarquía de vistas.
Contrato
- Entrada: layout XML con una capa extra de contenedor (por ejemplo un
FrameLayout) que únicamente envuelve unScrollViewy su contenido. - Salida: layout equivalente con el
ScrollViewcomo raíz (o sin la capa redundante). - Criterio de éxito: la UI resultante se comporta igual visualmente y en funcionalidad, pero con menor tiempo de inflado/medida/layout/dibujo, y menor uso de memoria temporal durante la creación.
Problema con la capa extra
- Cada ViewGroup adicional agrega trabajo durante las fases de inflado, measure, layout y draw.
- Android recorre la jerarquía en cada frame para estas operaciones. Menos nodos = menos trabajo.
- Una capa de
FrameLayoutque no aporta comportamiento (p. ej. no clipping, no z-order específico, sin listeners ni fondo necesario) es sobrecarga innecesaria.
Efectos concretos sobre el rendimiento
-
Inflado (inflation)
- El sistema tiene que parsear y crear un objeto extra. En UI complejas o pantallas que se inflan con frecuencia, esto suma.
- Menos objetos creados → menos presión sobre el GC.
-
Measure & Layout
- Measure y layout visitan cada View/ViewGroup; eliminar un nodo reduce las llamadas recursivas.
- En pantallas anidadas o profundas, el ahorro se amplifica (O(n) respecto al número de vistas).
-
Draw (renderizado) y Overdraw
- Aunque
FrameLayoutno siempre produce overdraw por sí mismo, capas extra pueden conllevar fondos superpuestos o invalidaciones adicionales. - Menos vistas implica menos trabajo en el pipeline de dibujo.
- Aunque
-
Memoria y GC
- Menos instancias de View → menos memoria usada y menos pausas por recolección de basura en escenarios de creación frecuente (p. ej. re-creación de Activity/Fragment).
Buenas prácticas relacionadas
- Evitar envoltorios innecesarios: eliminar ViewGroups que no añaden valor.
- Usar
mergecuando incluyes layouts que serán insertados en otro contenedor para evitar un contenedor extra. - Preferir
ConstraintLayoutpara layouts complejos por su capacidad de disminuir la profundidad de la jerarquía. - Para listas largas, usar
RecyclerViewen lugar de envolver muchos elementos en unScrollView. - Considerar
android:fillViewport="true"enScrollViewcuando desees que el contenido llene la pantalla y evitar medidas extra.
Eliminación de recursos sin usar
- Un
dimencon valor fijo muy grande (200dp) para unfab_marginsuele producir un espaciado excesivo e inflexible que rompe el diseño en muchas pantallas: en pantallas pequeñas puede empujar contenido fuera de la vista, y en pantallas grandes puede dejar huecos innecesarios.
Impactos negativos concretos
- UX y layout: un margen fijo de 200dp puede provocar que parte del contenido importante quede fuera del área visible, obligando a más scroll y aumentando la carga de medidas y dibujados.
- Medidas y performance: cuando el layout necesita más espacio (height) por el margen, Android hace más trabajo de measure/layout y posiblemente más invalidaciones durante cambios de orientación o redimensionado.
- Mantenibilidad: un valor arbitrario grande dentro de
dimens.xmldificulta la coherencia visual; es fácil que sea un remanente de pruebas manuales o valores temporales. - Accesibilidad y adaptabilidad: no responde bien a diferentes densidades, tamaños de pantalla ni configuraciones (split-screen, tablets, foldables).
Resumen de Micro-optimizaciones en el App
- Se ejecutaron análisis de Android Lint (Performance) — identificando varias mejoras anteriormente resumidas, (overdraw, invalidating RecyclerView, parents innecesarios, recursos no usados).
- Acciones clave implementadas:
- Eliminación de fondos redundantes y reduction de contenedores innecesarios (aplanamiento de la jerarquía de vistas).
- Limpieza de recursos no usados (dimens, drawables, etc.).
- Refactor de
AlbumsAdapteryMusiciansAdapteraListAdapter+DiffUtilpara evitarnotifyDataSetChanged()y reducir rebinding. - Migración a Glide con caching (memory + disk), placeholders y fallback para optimizar carga de imágenes y fluidificar scrolls.
- Mantener corutinas + Retrofit para llamadas de red no bloqueantes (ya presente desde SP1).
- Resultado observable tras la iteración:
- Warnings reducidos a 0
- Menor trabajo en CPU/GPU durante updates de lista (menos rebinds, preservación de animaciones).
- Scroll más fluido, menor consumo de red por caching y menor uso temporal de memoria por cargas de imágenes más eficientes.
- Inflado/measure/layout ligeramente más rápidos por jerarquía más plana y eliminación de márgenes/recursos innecesarios.