Resumen de optimización del rendimiento del desarrollo de Android (1)

El desarrollo de aplicaciones de Android primero debe prestar atención a una buena experiencia de usuario. Si un software se bloquea gravemente, no es fluido y, a menudo, falla, traerá a los usuarios una experiencia muy mala y los perderá.
En el desarrollo y el aprendizaje reales, resumí la optimización del rendimiento de Android para su referencia e intercambio.

Los problemas de rendimiento de la aplicación se reflejan en muchos aspectos, como la velocidad de inicio lenta por primera vez o la velocidad lenta de ingresar a una interfaz determinada; el proceso de ejecución de la animación no es fluido o la ejecución de la animación se congela durante mucho tiempo ; La velocidad de ejecución de una interfaz específica personalizada por el programa es lenta; no hay respuesta (ANR) durante mucho tiempo al responder a un determinado evento de usuario; al operar la base de datos, la adición, eliminación, modificación y consulta de una gran se realiza una gran cantidad de datos y la velocidad de ejecución es lenta; el archivo se lee y escribe con frecuencia, y el archivo de caché es demasiado grande Provoca bloqueos; después de que la aplicación se ha estado ejecutando durante mucho tiempo, los bloqueos ocurren aleatoriamente.

Puede haber más de una razón para los problemas anteriores. En algunos casos, puede que no sea un problema con la aplicación en sí, o puede ser un problema con otras capas del sistema, pero solo se refleja en la capa de la aplicación. Por lo tanto, cuando los desarrolladores se enfrentan a problemas de rendimiento, lo primero que deben hacer es juzgar si el problema de rendimiento es causado por la aplicación en sí y luego recetar el medicamento adecuado; pero a veces la lógica de la aplicación en sí es normal, pero debido debido a una configuración de hardware insuficiente del sistema, se producen anomalías. En este momento, es necesario adoptar algunos métodos más precisos para optimizar el rendimiento de acuerdo con los requisitos del producto o proyecto para compensar la falta de configuración de hardware.

A continuación se resumen algunos métodos de optimización del rendimiento de las aplicaciones desde varios ángulos diferentes.

1. Ideas de programación

La optimización del rendimiento en la capa de aplicación generalmente se puede considerar desde los siguientes aspectos:

  1. Comprender los principios de compilación de los lenguajes de programación y utilizar métodos de codificación eficientes para mejorar el rendimiento del programa sintácticamente;
  2. Utilizar estructuras de datos y algoritmos razonables para mejorar el rendimiento del programa, que suele ser la clave para el rendimiento del programa;
  3. Preste atención a la optimización del diseño de la interfaz;
  4. Use subprocesos múltiples, datos de caché, carga diferida, carga temprana y otros medios para resolver cuellos de botella de rendimiento graves;
  5. Configure razonablemente el límite superior y la tasa de utilización de la memoria de almacenamiento dinámico de la máquina virtual para reducir la frecuencia de recolección de elementos no utilizados;
  6. Uso razonable de código nativo;
  7. Configure razonablemente el tipo de caché de la base de datos y optimice la declaración SQL para acelerar la velocidad de lectura y use transacciones para acelerar la velocidad de escritura;
  8. Utilice herramientas para analizar los problemas de rendimiento y encontrar cuellos de botella en el rendimiento;
    por supuesto, debe haber muchos otros métodos de optimización del rendimiento, y estos son solo algunos de los métodos más utilizados.

2. Habilidades de programación
Hay algunos consejos para mejorar el rendimiento de la aplicación en el sitio web oficial de Android. Aquí hay una breve lista y parte de mi propia experiencia en el desarrollo real. Los detalles se pueden obtener en los documentos del sitio web oficial .
Cabe señalar que las técnicas de optimización enumeradas en el artículo son principalmente algunas mejoras menores de rendimiento, y el rendimiento general del programa aún depende del diseño de la lógica comercial del programa, la estructura de datos y el algoritmo del código. El personal de I+D debe aplicar estas técnicas de optimización al proceso de codificación habitual, lo que tendrá un gran impacto en el rendimiento.
Para escribir código eficiente, debe seguir dos principios:
no realice operaciones innecesarias;
no asigne memoria innecesaria;
los dos principios están dirigidos respectivamente a la CPU y la memoria, y ahorre recursos de CPU y memoria tanto como sea posible bajo la premisa de completar operaciones necesarias La eficiencia de ejecución debe ser alta. Simplemente decir esto suena vacío, después de todo, no existe un estándar unificado para juzgar lo que es necesario e innecesario, y debe analizarse en combinación con situaciones específicas.
1. Evita crear objetos innecesarios
Crear objetos tiene un costo. Un recolector de elementos no utilizados generacional con un grupo de asignación a nivel de subprocesos para objetos temporales puede reducir los costos de asignación, pero asignar memoria siempre es más costoso que no asignar memoria. La creación de demasiados objetos provocará un rendimiento deficiente. En primer lugar, se necesita tiempo para asignar la memoria. En segundo lugar, existe un límite superior en el uso de la memoria del montón cuando la máquina virtual se está ejecutando. Cuando el uso alcanza un cierto nivel, la recolección de elementos no utilizados será La recolección de basura creará subprocesos e incluso todo el proceso se suspenderá. Es concebible que si los objetos se crean y destruyen con frecuencia, o si el uso de la memoria es alto, la aplicación se atascará gravemente.
2. Uso razonable de estático
Si no necesita acceder a un campo de un objeto, haga que el método correspondiente sea estático. La velocidad de la llamada aumentará entre un 15 % y un 20 %.
Hay tres puntos principales a comprender:
Si un método no necesita operar métodos y variables dinámicas en tiempo de ejecución, entonces el método puede configurarse como estático.
El campo constante debe declararse como "final estático", porque la constante se almacenará en el inicializador de campo estático del archivo dex y se accederá directamente; de ​​lo contrario, algunas funciones deben inicializarlo automáticamente generado en tiempo de compilación en tiempo de ejecución. Esta regla solo es válida para tipos primitivos y tipos String.
No declare el control de vista como estático, porque el objeto Vista se referirá al objeto Actividad. Cuando la Actividad sale, el objeto en sí no se puede destruir, lo que provocará un desbordamiento de memoria.
3. Evite Getters/Setters internos
En el diseño orientado a objetos, generalmente es un buen principio usar Getters/Setters para el acceso a campos, pero limitado a las condiciones de hardware en el desarrollo de Android, a menos que el campo deba ser accedido públicamente, de lo contrario, si es solo un rango limitado de acceso For interno (como el acceso dentro de un paquete), no se recomienda usar Getters/Setters. Cuando JIT está activado, el acceso directo es 7 veces más rápido que el acceso indirecto.
4. Usar bucles for mejorados
Priorizar el uso de bucles for mejorados en general para obtener una mayor eficiencia, excepto en un caso, es decir, al atravesar el ArrayList, usar bucles for ordinarios es más eficiente.
5. Para las clases internas privadas, considere usar derechos de acceso a paquetes en lugar de derechos de acceso privados.
Los métodos de las clases internas privadas acceden a las variables miembro privadas y los métodos de las clases externas, lo cual es gramaticalmente correcto, pero la máquina virtual no accede directamente a ellos en En su lugar, algunos métodos estáticos a nivel de paquete se generarán automáticamente en la clase externa en tiempo de compilación, y la clase interna llamará a estos métodos estáticos para acceder a los miembros privados de la clase externa durante la ejecución. En este caso, hay una capa adicional de llamadas a métodos y se pierde el rendimiento.
Una forma de resolver este problema es cambiar los miembros privados de la clase externa al nivel del paquete, de modo que se pueda acceder directamente a la clase interna, por supuesto, la premisa es que el diseño sea aceptable.
6. Evite el uso de tipos de punto flotante
En los dispositivos Android, los tipos de punto flotante son aproximadamente el doble de lentos que el procesamiento de datos enteros, por lo que si los números enteros pueden resolver problemas, no use tipos de punto flotante.
Además, algunos procesadores tienen multiplicación de hardware pero no división, en cuyo caso las operaciones de división y módulo se implementan en el software. Para mejorar la eficiencia, puede considerar reescribir directamente algunas operaciones de división como multiplicaciones al escribir expresiones de cálculo, por ejemplo, reescribir "x / 2" como "x * 0.5".

7. Adopte <merge>capas de diseño optimizadas. Adopte <include>para compartir el diseño.
8. Retrasar la vista de carga. Use ViewStub para evitar que se haga referencia a algunas vistas poco frecuentes durante mucho tiempo y ocupen memoria.
9. Elimine el fondo predeterminado de la actividad para mejorar la velocidad de carga de la actividad.
Si está seguro de que está utilizando un fondo opaco en su Actividad, puede eliminar el fondo predeterminado de la Actividad.
En el código: getWindow().setBackgroundDrawable(null);
también se puede establecer en el archivo de estilo de estilos y configurar en el archivo de manifiesto

 <style name="MyStyle" parent="AppTheme">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@null</item>  
 </style>

10. Uso del cursor .
Preste atención para administrar bien el cursor, no abra y cierre el cursor cada vez, porque abrir y cerrar el cursor lleva mucho tiempo.
Recuerde cerrar el cursor que ya no se usa (generalmente se ejecuta en el bloque de instrucción finalmente).
Hay una situación en la que no podemos cerrar el Cursor directamente, que es el caso en el CursorAdapter, pero tenga en cuenta que el CursorAdapter no cierra automáticamente el Cursor cuando finaliza la Actividad, por lo que debe cerrarlo manualmente en la función onDestroy.

protected void onDestroy() { 
      if (mAdapter != null && mAdapter.getCurosr() != null) { 
	      mAdapter.getCursor().close(); 
      } 
      super.onDestroy(); 
	}

11. Al transmitir el registro dinámico de BroadCast, recuerde anular el registro del receptor al final del ciclo de vida de la persona que llama para evitar pérdidas de memoria.
12. Optimice el rendimiento de
los elementos de ListView para reducir el nivel de controles y diseños utilizados tanto como sea posible; el color de fondo se establece en el mismo color que cacheColorHint; el diseño de los elementos en ListView es muy importante, y los controles y diseños utilizados debe reducirse lo más posible. RelativeLayout es un arma absoluta, a través de la cual puedes reducir el nivel de diseño. Al mismo tiempo, es necesario reutilizar los controles tanto como sea posible, lo que puede reducir el uso de memoria de ListView y reducir la cantidad de GC al deslizar. El color de fondo de ListView se establece en el mismo color que cacheColorHint, lo que puede mejorar el rendimiento de representación al deslizar. El rendimiento de getView en ListView es la clave y debe optimizarse tanto como sea posible aquí. La vista debe reutilizarse en el método getView; los cálculos lógicos complejos, especialmente las operaciones de la base de datos, no se pueden realizar en el método getView; de lo contrario, afectará seriamente el rendimiento del deslizamiento; cuando hay muchos elementos de datos en ListView, considere la carga de paginación.
13. Preste atención al uso del mecanismo de sincronización de subprocesos (sincronizado) para evitar que se produzcan excepciones cuando varios subprocesos acceden a un objeto al mismo tiempo.
14. Uso razonable de StringBuffer, StringBuilder y String
En la concatenación de cadenas simple, String es el más eficiente, por ejemplo, String s = "hola" + "mundo",
pero todos deben prestar atención aquí, si su cadena es de otra cadena. objeto, la velocidad no es tan rápida, por ejemplo:
    String str2 = "Esto es";
    String str3 = "a";
    String str4 = "prueba";
    String str1 = str2 + str3 + str4;
Aquí se requiere StringBuilder
. En un solo hilo, el rendimiento de StringBuilder es mayor que el de StringBuffer. Los subprocesos múltiples deben usar StringBuffer para la seguridad de los subprocesos, ya que está sincronizado. En circunstancias normales, generalmente se usa StringBuilder.
15. Trate de usar variables locales,
los parámetros pasados ​​al llamar al método y las variables temporales creadas durante la llamada se almacenan en la pila (Stack), que es más rápido. Otras variables, como variables estáticas, variables de instancia, etc., se crean en el montón (Heap), que es más lento. Además, dependiendo del compilador/JVM específico, las variables locales pueden optimizarse aún más.
16. Recuerde cerrar el objeto de flujo a tiempo para las operaciones de flujo de E/S.
17. Use IntentService en lugar de Service
IntentService y Service son ambos un servicio, la diferencia es que IntentService usa una cola para agregar el Intent solicitado a la cola y luego inicia un subproceso de trabajo (subproceso) para procesar el Intent en la cola (en el método onHandleIntent), para las solicitudes de startService asincrónicas, IntentService procesará una y luego procesará la segunda. Cada solicitud se procesará en un subproceso de trabajo separado, que no bloqueará el subproceso principal de la aplicación. Si hay un tiempo- operación que consume, es mejor iniciarlo en el Servicio. Un nuevo subproceso también podría usar IntentService para manejar operaciones que consumen mucho tiempo.
18. Usar contexto de aplicación en lugar de contexto en actividad
No permitir que objetos con un ciclo de vida largo se refieran al contexto de actividad, es decir, asegurarse de que el objeto que se refiere a la actividad tenga el mismo ciclo de vida que la actividad misma.
Para objetos con un ciclo de vida largo, puede usar el contexto de la aplicación
en lugar de configurar el objeto de contexto como estático.
19. Los objetos de la colección deben limpiarse a tiempo.
 Por lo general, agregamos algunas referencias de objetos a la colección. Cuando no necesitamos el objeto, no limpiamos sus referencias de la colección, por lo que la colección se convertirá en más y más grande. . Si la colección es estática, la situación es aún más grave.
20. Uso de
mapas de bits Preste atención a la compresión para mapas de bits más grandes antes de usarlos. Cuando cargue imágenes grandes de alta definición, puede considerar el uso de BitmapRegionDecoder. Preste atención a recycle()  a tiempo para los mapas
de bits no utilizados.
) hábilmente
Después de usar el mapa de bits, no se guarda ninguna referencia, por lo que no se puede llamar a la función Recycle. En este momento, el uso inteligente de referencias suaves puede hacer que el mapa de bits se libere de manera efectiva cuando la memoria se está agotando. Para obtener una introducción al mecanismo de referencia de Java, puede leer mi otro blog: Cuatro tipos de referencia de objetos Java
22. Trate de no usar toda la imagen grande como un archivo de recursos, intente usar imágenes de 9 rutas
(entorno), otros mapas de recursos, y .9 los mapas deben colocarse en drawable-xxxx, y las imágenes que deben copiarse en la tarjeta SD del teléfono móvil deben colocarse en el directorio de activos; el uso de imágenes webp en lugar de png puede reducir considerablemente el tamaño de la imagen.
23. Comprender y usar funciones de biblioteca
La biblioteca estándar de Java y el marco de trabajo de Android contienen una gran cantidad de funciones de biblioteca eficientes y sólidas, y muchas funciones se implementan de forma nativa, lo que suele ser mucho más eficiente que el código que implementa la misma función en Java. Por lo tanto, ser bueno en el uso de las funciones de la biblioteca del sistema puede ahorrar tiempo de desarrollo y no es propenso a errores.
24. Con respecto a WebView,
recuerde destruir WebView cuando se destruya Actividad o Fragmento

@Override
    protected void onDestroy() {
        if (webView!= null) {
            webView.destroy();
            webView= null;
        }
        super.onDestroy();
    }

25. El uso razonable de JNI
y Android NDK para desarrollar aplicaciones usando código nativo no es necesariamente más eficiente que programar en lenguaje Java. Primero, hay costos asociados con las transiciones Java-Native, y el JIT no puede optimizarse fuera de estos límites. Si está asignando recursos nativos (memoria en el almacenamiento dinámico nativo, descriptores de archivo o cualquier otro elemento), puede ser mucho más difícil organizar que estos recursos se recuperen de manera oportuna. También necesita compilar su código para cada arquitectura en la que desee ejecutarlo. También es posible que deba compilar varias versiones de la biblioteca so para diferentes arquitecturas de CPU.
El código nativo está diseñado principalmente para los casos en los que desea transferir una base de código nativo existente a Android, no para "acelerar" partes de una aplicación de Android escrita en lenguaje Java.
26. Haga un buen uso del mecanismo de captura de excepciones.
Java proporciona un bloque de sintaxis try-catch para capturar las excepciones del código. En el desarrollo diario, no podemos considerar completamente muchas situaciones y las excepciones pueden ocurrir en cualquier momento. Un código sólido debe incluir el manejo de excepciones. Mecanismo, el uso razonable de try-catch puede evitar el problema de que muchas aplicaciones se bloqueen y también puede ayudar a los desarrolladores a localizar rápidamente el problema.
27. Optimización del consumo de energía
El consumo de energía de la aplicación se refleja principalmente en:
1. Creación frecuente de objetos, operaciones que consumen mucho tiempo u operaciones de cálculo complejas
2. La aplicación activa activamente la pantalla o controla que la pantalla esté siempre encendida y aumenta activamente el brillo de la pantalla
3. Temporización en segundo plano Las tareas y los servicios se ejecutan durante mucho tiempo
Los desarrolladores pueden considerar cómo optimizar estas operaciones para ahorrar energía en función de estos tres puntos.

3. Use herramientas para analizar el rendimiento de la aplicación
(esta parte tiene más contenido, consulte "Resumen de optimización del rendimiento de desarrollo de Android (2)" para obtener más detalles .

Supongo que te gusta

Origin blog.csdn.net/gs12software/article/details/51173392
Recomendado
Clasificación