Optimización del rendimiento de Android. Cuando escribimos código Android, nuestro… | de Sonika Srivastava | julio 2022

Cuando escribimos código de Android, nuestro enfoque se centra principalmente en la interfaz de usuario, el manejo de eventos, las tareas en segundo plano y la integración de back-end. Apenas pensamos en el rendimiento de la aplicación y, por lo general, lo damos por sentado. Aquí discutiremos algunos aspectos importantes que afectan en gran medida el rendimiento de nuestra aplicación y también comprenderemos los pasos que pueden tomar los desarrolladores para mejorar el rendimiento.prestarNormalmente, el sistema intenta volver a dibujar la actividad aproximadamente cada 16 ms. ¿Cómo nos afecta esto?

  • El hardware del teléfono determina la velocidad a la que la pantalla puede actualizarse. La mayoría de los dispositivos se actualizan alrededor de los 60 Hz, es decir, 1000 ms/60 Hz ~ 16,66 ms.
  • Así, el sistema sólo dispone de unos 16 ms para ejecutar toda la lógica de dibujo. Si se pierde el intervalo de 16 ms, se perderán fotogramas. Esto dificulta la fluidez de las animaciones. Múltiples instancias de este tipo resultan en tartamudeo y una experiencia de retraso.
  • Por lo tanto, debemos tener en cuenta que las animaciones y transiciones sofisticadas pueden no funcionar muy bien en todos los dispositivos Android.

La canalización de renderizado de Android se divide en dos subsistemas: GPU y CPU. El proceso de convertir XML en pantallas se llama rasterización.

  • Aquellos que hayan creado una vista personalizada pueden estar familiarizados con los pasos para representar una vista (como se muestra a continuación).

  • La rasterización es un proceso que consume mucho tiempo y la GPU está diseñada para acelerar este proceso. Por lo tanto, debemos intentar minimizar estos pasos tanto como sea posible.
  • Si seguimos cambiando los objetos, p. Por ejemplo, cambiar el color de fondo, el texto, el tamaño, etc. repetirá el proceso anterior cada vez.
  • El proceso de renderizado consume cada vez más tiempo a medida que la interfaz de usuario se vuelve más y más compleja.
  • En el lado de la GPU, el problema más importante es el «sobredibujado», que es desperdiciar ciclos de GPU dibujando y coloreando píxeles que eventualmente se desvanecen.
  • Overdraw es un término utilizado para describir la cantidad de veces que se vuelve a dibujar un píxel en una pantalla en un solo cuadro. una pila de cartas de IU apiladas, solo la carta superior es visible, pero todas las cartas están robadas.
  • Los desarrolladores pueden considerar lo siguiente al escribir el código de la interfaz de usuario.

i) Cada vez que dibujamos algo que no forma parte de la escena final desperdiciamos ciclos de GPU. ii) Evite las interfaces de usuario apiladas o en capas. Opción de sobredibujado. Android utiliza un esquema de color para indicar el nivel de sobredibujado. Busque áreas rojas para reducir el exceso. Elimine los colores de fondo innecesarios. Y busque áreas que estén ocultas.Papel de la CPU en el renderizado:

  • Para dibujar algo en la pantalla, la CPU tiene que convertir XML de alto nivel en objetos que la GPU pueda entender. Esto se hace usando una lista de visualización.
  • Si necesitamos volver a renderizar un objeto, p. B. si la posición de un elemento de la interfaz de usuario cambia, debemos reconstruir la lista de visualización y ejecutarla de nuevo porque la vista deja de ser válida. Además, cuando se reposicionan otras vistas debido a un cambio en una vista, la lista de visualización de cada diseño se reconstruye y vuelve a ejecutar.
  • Cuando cambia el tamaño de la vista, se vuelve a llamar al método onMeasure() y se vuelve a examinar toda la jerarquía de la vista.
  • Si se cambia la posición de la vista, se vuelve a llamar al método requestLayout().
  • Por lo tanto, cuando la jerarquía de vistas es muy compleja, las partes de «Medida» y «Diseño» de la canalización de representación pueden causar problemas de rendimiento.
  • visor de jerarquía ayuda a comprender el diseño general y elimina las vistas de rutina, y también puede ayudar a aplanar la jerarquía de vistas.
  • Como desarrolladores, debemos tener en cuenta que los diseños anidados afectan el rendimiento y la capacidad de respuesta de la interfaz de usuario. Por ejemplo, utilice el diseño de restricciones y el diseño relativo en lugar del diseño lineal anidado.

memoriaPara entender la optimización de la memoria, necesitamos entender los conceptos básicos de recolección de basura.

  • Aunque Java viene con un recolector de basura y la gestión de la memoria no es la principal preocupación del desarrollador, las fugas de memoria aún pueden causar problemas de rendimiento.
  • Garbage Collector, en pocas palabras, funciona en 2 pasos: marcar y barrer, es decir, encontrar objetos a los que no se puede acceder y recuperar los recursos de ellos. Pero es muy, muy difícil averiguar a qué objetos no se accede, cuándo ejecutar el recolector de basura y evitar la memoria fragmentada, lo que lo hace muy complicado.
  • El montón de memoria en el tiempo de ejecución de Android se divide en diferentes áreas según cómo se asigna y cómo el sistema puede organizar mejor los objetos para futuros eventos de GC. Cuando se asigna un nuevo objeto, se respetan estas propiedades y se elige la ubicación del montón con el mejor ajuste.
  • Cada área tiene un tamaño fijo. Al asignar objetos, el sistema realiza un seguimiento de los tamaños combinados. A medida que crece el espacio en disco, el sistema ejecuta un GC para liberar espacio en disco.
  • El comportamiento de GC depende del tiempo de ejecución de Android. En Dalvik, las operaciones de GC pueden pausar el proceso de ejecución actual hasta que se complete. Esto puede ralentizar el proceso si GC tarda más tiempo o si se llama a GC con demasiada frecuencia. Por ejemplo, si GC tarda más, puede hacer que la operación de extracción pierda el marco de 16 ms, lo que a su vez provoca un bloqueo.
  • El nuevo ART GC o Generational GC está más optimizado y se ejecuta en paralelo al proceso que se está ejecutando actualmente.
  • Cuanto más tiempo se pasa durante la GC, menos tiempo se dedica a otras tareas, como el renderizado o el cálculo.
  • Los objetos no utilizados que aún no ha publicado GC provocan fugas de memoria.

monitor de memoria puede mostrar cómo la aplicación utiliza la memoria a lo largo del tiempo.¿Qué son las fugas de memoria?

  • Cada segmento de montón tiene un límite de memoria. Cuando el límite está casi agotado, se activa un GC. Los eventos de GC muy frecuentes pueden afectar el rendimiento.
  • Las fugas de memoria conducen a GC muy frecuentes. Los objetos filtrados son aquellos que ya no se necesitan, pero el recolector de basura no se da cuenta de que ya no se accede a ellos. Como resultado, el espacio disponible en el montón se vuelve cada vez más pequeño. Esto conduce a un escenario en el que se ejecutan más GC con mayor frecuencia para liberar espacio en disco.
  • Las fugas de memoria son lentas e insidiosas. Pueden pasar días antes de que nos demos cuenta de que tenemos una pérdida de memoria.

visor de montones puede ayudarnos a ver cuánta memoria usa nuestra aplicación. Podemos saber «qué» está en el montón.Escenarios comunes de pérdida de memoria:

  1. Uso de vista/contexto estático : las vistas estáticas y los objetos de contexto se mantienen en la memoria hasta que la aplicación finaliza, y la memoria que usan no se recolecta como basura. Evite usar el contexto como una variable estática o en un objeto complementario en Kotlin.
  2. Olvidé dar de baja a los oyentes: si no anulamos el registro de los oyentes, la memoria utilizada no se recuperará del recolector de elementos no utilizados, incluso si no está en uso. Este problema se agrava cuando se destruye la actividad y se crea una nueva, p. B. durante la rotación del dispositivo. Cada vez que la vista crea un nuevo oyente que nunca se publica. Por lo tanto, nunca se recupera ningún agente de escucha de GC, y esto resultó en una pérdida de memoria.
  3. Clase anidada no estática: si la clase anidada no es estática, implícitamente contiene la referencia a la clase externa y, por lo tanto, la clase externa permanece activa hasta que la aplicación está activa.
  4. Pasar el contexto a la biblioteca de terceross: Pase siempre getApplicationContext() para inicializar bibliotecas de terceros; de lo contrario, la biblioteca utilizará el contexto de la actividad en un contexto estático y la actividad no se recolectará como basura hasta que finalice la aplicación.
  5. mapas de bits: Los mapas de bits pueden agotar fácilmente la memoria de la aplicación. Por lo tanto, debemos reducir, reutilizar y reciclar los mapas de bits tanto como sea posible. También podemos usar bibliotecas de terceros como Glide que ayudan a optimizar el uso de mapas de bits.

bateria y redSi bien no es muy obvio, parte de nuestro código puede terminar consumiendo más batería.

  • Cada vez que encendemos la pantalla se produce un enorme aumento del consumo de batería. Encender LED, pintar la pantalla, operaciones de CPU, GPU, etc. requieren mucha energía.
  • Hay un gran consumo de batería cuando la aplicación activa el dispositivo, p. B. Wake Lock, Administrador de alarmas o Programador de trabajos. Mantener el dispositivo despierto para hacer poco o ningún trabajo es una pérdida de vida útil de la batería.
  • Para reducir el consumo de la batería de wakelock, retrase las operaciones de uso intensivo de la batería a momentos en que el teléfono se está cargando o conectado a Wi-Fi. La API del programador de trabajos es la elección correcta para programar o agrupar operaciones futuras.
  • Las redes son las mayores culpables del agotamiento de la batería. Hay un chip de radio que se comunica con la torre celular y le comunica datos a granel. Si es posible, realice operaciones de red en segundo plano cuando esté conectado a WIFI para evitar el uso celular. Sin embargo, escribir el código para apilar, almacenar en caché y retrasar las solicitudes de red es una tarea realmente complicada. Nuevamente, las API del programador de trabajos pueden ayudar.

Perfilador de red se puede utilizar para visualizar esto:Si tenemos en cuenta estos aspectos a la hora de desarrollar la app, podemos evitar muchos problemas de rendimiento en nuestra aplicación desde el primer momento.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.