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 un ScrollView y su contenido.
  • Salida: layout equivalente con el ScrollView como 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 FrameLayout que 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

  1. 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.
  2. 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).
  3. Draw (renderizado) y Overdraw

    • Aunque FrameLayout no 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.
  4. 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 merge cuando incluyes layouts que serán insertados en otro contenedor para evitar un contenedor extra.
  • Preferir ConstraintLayout para layouts complejos por su capacidad de disminuir la profundidad de la jerarquía.
  • Para listas largas, usar RecyclerView en lugar de envolver muchos elementos en un ScrollView.
  • Considerar android:fillViewport="true" en ScrollView cuando desees que el contenido llene la pantalla y evitar medidas extra.

Eliminación de recursos sin usar

  • Un dimen con valor fijo muy grande (200dp) para un fab_margin suele 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.xml dificulta 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 AlbumsAdapter y MusiciansAdapter a ListAdapter + DiffUtil para evitar notifyDataSetChanged() 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.