Optimización del rendimiento para el desarrollo de Android: solución de dibujo de transición

1. Dibujo de transición

Un determinado píxel en la pantalla se dibuja repetidamente varias veces en un cuadro, que es un dibujo de transición.
La imagen a continuación muestra varias cartas cayendo juntas, pero solo la primera carta es completamente visible. Las cartas detrás son solo parcialmente visibles. Sin embargo, el sistema Android sacará las cartas inferiores al dibujar y luego sacará las cartas superiores. Pero, de hecho, no es necesario dibujar la parte invisible de la carta inferior, solo se necesita dibujar la parte visible.

Según el nivel de dibujo de transición, se puede dividir en:

  • Dibujar sin transiciones (un píxel se dibuja una sola vez)
  • dibujo de transición x1 (un píxel se dibuja dos veces)
  • dibujo de transición x2 (un píxel se dibuja tres veces)
  • Overdraw x3 (un píxel se dibuja cuatro veces)
  • Overdraw x4+ (un píxel se dibuja más de cinco veces)

2. Vea el dibujo de transición de su aplicación

Método 1: habilite la depuración de procesamiento de transición de GPU a través de las opciones de desarrollador

En las opciones de desarrollador del teléfono Android, existe la opción de "depurar sobredimensionamiento de GPU":

Después de hacer clic en él, seleccione "Mostrar área de dibujo de transición":

Método 2: habilite la depuración de procesamiento de transición de GPU a través del comando adb

Por supuesto, si es problemático ingresar la configuración del sistema cada vez, puede usar el comando adb para encenderlo y apagarlo:
active "Depurar sobredimensionamiento de GPU":

adb shell setprop debug.hwui.overdraw show

Desactive "Depurar GPU Overdraw":

adb shell setprop debug.hwui.overdraw false

Puede ser necesario reiniciar la aplicación que está desarrollando actualmente después de ejecutar el comando.

Dibujo de color y transición:

  • Colores primarios: sin sobregiro
  • Azul: 1 sobregiro
  • Verde: 2 sobregiros
  • Rosa: 3 sobregiros
  • Rojo: 4 o más sobregiros

En el desarrollo normal, si hay una situación de dibujo de transición de rosa y superior. Las instrucciones para sobregirar también son bastante estrictas. Necesita ser optimizado.

3. Optimizar el dibujo de transición

1. Elimina el color de fondo predeterminado que viene con la Actividad:

Vea el tema Tema en el código fuente de Android, de la siguiente manera:

<style name="Theme">
    ...
    <!-- Window attributes -->
    <item name="windowBackground">@drawable/screen_background_selector_dark</item>
    ...
</style>

Es decir, heredando el estilo de Tema, por defecto, la creación de una nueva Actividad tiene un fondo. En circunstancias normales, muchas interfaces en realidad no necesitan un fondo.

La siguiente es la página de inicio de la aplicación meteorológica integrada de Huawei. Podemos ver que el texto y los íconos son verdes. La superficie ya está dibujada en la tercera capa de transición. El mapa meteorológico detrás es una capa, y el texto es otra. capa Es normal Se dice que solo debe haber dos capas, es decir, el texto y los íconos deben ser azules.

Luego, esta capa adicional debería ser el color de fondo que viene con la actividad. Eso está fijado en el tema.

Solo necesitamos eliminar el color de fondo en nuestro AppTheme:

<style name="AppTheme" parent="android:Theme.Light.NoTitleBar">
    <item name="android:windowBackground">@null</item>
</style>

O en el método onCreate de la actividad:

getWindow().setBackgroundDrawable(null);

2. Use los métodos clipRect y clipPath de Canvas para limitar el área de dibujo de View

Una actividad corresponde a un lienzo, que es el lienzo. El concepto del lienzo es un tablero de dibujo. Este lienzo proporciona muchas API. Podemos dibujar y realizar algunas operaciones en el lienzo llamando a la API del lienzo. El método clipRect es utilizado para cortar el lienzo.Un área rectangular de, que se describe mediante un objeto Rect. Después de llamar a clipRect, el área dibujable del lienzo se reduce al mismo tamaño que el área rectangular especificada por Rect. Todo dibujo se limitará a este rectángulo. El concepto de recorte aquí es similar al de PS.

Un ejemplo típico, diseño de cajón, encontré Netease Cloud Music para hacer la cirugía:

imagen.png

Preste atención para observar que cuando se abre el cajón izquierdo, el diseño del cajón se superpone con el diseño posterior. En este momento, más de la mitad de la pantalla se vuelve roja y el dibujo de transición es serio.

Cuando aparece el diseño del cajón, el diseño del cajón es opaco, lo que significa que no es necesario dibujar el diseño del contenido detrás del diseño del cajón, pero NetEase Cloud lo dibuja, lo que hace que los píxeles en el área donde se encuentra el diseño del cajón se vean dibujado varias veces.

Google tiene oficialmente la clase DrawerLayout.Java bajo el paquete android.support.v4.widget. Se utiliza para implementar el diseño del cajón. Esta clase anula el método drawChild:

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    final int height = getHeight();
    // 判断是否是内容视图
    final boolean drawingContent = isContentView(child);
    int clipLeft = 0, clipRight = getWidth();

    // 记录当前画布信息
    final int restoreCount = canvas.save();
    if (drawingContent) {
        // 只有在绘制内容视图时才进行裁切
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View v = getChildAt(i);
            if (v == child || v.getVisibility() != VISIBLE ||
                    !hasOpaqueBackground(v) || !isDrawerView(v) ||
                    v.getHeight() < height) {
                // 如果child是内容视图/视图不可见/视图背景透明/不是抽屉视图/child高度小于父布局高度
                // 则不做画布裁切
                continue;
            }

            if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
                // 盒子在左侧时裁切的left和right
                final int vright = v.getRight();
                if (vright > clipLeft) clipLeft = vright;
            } else {
                // 盒子在右侧时裁切的的left和right
                final int vleft = v.getLeft();
                if (vleft < clipRight) clipRight = vleft;
            }
        }
        // 裁切画布
        canvas.clipRect(clipLeft, 0, clipRight, getHeight());
    }
    // 绘制子视图
    final boolean result = super.drawChild(canvas, child, drawingTime);
    // 回复到裁切之前的画布
    canvas.restoreToCount(restoreCount);
}

El método drawChild se llama en el método dispatchDraw de la clase ViewGroup para dibujar subvistas. La clase DrawerLayout anula este método porque se llama al método drawChild antes de que se dibujen todas las vistas secundarias, pero aquí solo se necesita cortar la vista del área de contenido. Al dibujar la vista del área de contenido, obtenga la información de posición de la vista del cajón. Si la vista del cajón está visible, el fondo es opaco y la altura del cajón es consistente con la altura del diseño principal, obtenga la información de posición de la izquierda, bordes superior, derecho e inferior de la vista del cajón en el lienzo. Luego corte, recorte la parte de la vista de contenido que no está bloqueada y entregue el lienzo cortado a la Vista secundaria para que dibuje, de modo que el área de contenido solo se dibuje en el área de corte y no se dibujen otras áreas. dibujar

Después de dibujar la subvista, restaure el lienzo al estado que tenía antes de cortar, ya que todas las vistas debajo de una ventana usan el mismo lienzo, por lo que es necesario restaurar el estado para que lo usen otras subvistas.

Veamos la aplicación de "descarga" en un sistema, que está implementado por DrawerLayout:

Aunque el área de contenido es roja en la aplicación, después de extraer la vista del cajón, el dibujo de transición de la vista del cajón es menor que el de la parte sin obstrucciones del área de contenido.

3. El fondo de ImageView y la superposición de imageDrawable

En Android, todas las vistas pueden establecer el fondo. Además de configurar el fondo, ImageView también puede configurar ImageDrawable.

En el desarrollo, a menudo es necesario mostrar una imagen. Antes de cargar la imagen, generalmente es necesario mostrar una imagen predeterminada. En muchos casos, la propiedad de fondo de ImageView se usa para establecer la imagen de fondo predeterminada y se usa imageDrawable. para configurar la imagen que se va a cargar. Esto causará un problema.Cuando la imagen se carga en la página, la imagen de fondo predeterminada se bloquea, pero aún debe dibujarse, lo que resulta en un dibujo de transición.

La solución es establecer tanto la imagen de fondo como la imagen realmente cargada a través del método imageDrawable .

4. Resumen

  • Una ventana en Android corresponde a un lienzo, y todas las vistas (View/ViewGroup) debajo de la ventana usan el mismo lienzo, y el nodo principal del árbol de vista cortará el lienzo antes de llamar al View.draw de la subvista. el área rectangular ocupada por la Vista en la pantalla, por lo que se cortará el contenido más allá del borde de la Vista.

  • Dado que un píxel del valor del dibujo de transición se dibuja varias veces, solo debemos asegurarnos de que las imágenes o los colores de fondo no se superpongan. La forma correcta debería ser minimizar el área superpuesta de Ver con el fondo. Si se superpone, use el clipRect del lienzo para recortar.

  • Minimice la profundidad de la vista para reducir el proceso transversal del árbol de vistas.

por fin

Finalmente, quiero decir: para los programadores, hay demasiado contenido de conocimiento y tecnologías para aprender. Si no quieres ser eliminado por el entorno, debes mejorar constantemente. Siempre nos hemos adaptado al entorno, no al entorno . para adaptarse a nosotros. !

Para ayudar a todos a comprender mejor la optimización del rendimiento de una manera completa y clara, hemos preparado notas principales relevantes (volviendo a la lógica subyacente):https://qr18.cn/FVlo89

Notas básicas de optimización del rendimiento:https://qr18.cn/FVlo89

Optimización de inicio

Optimización de memoria Optimización

de interfaz de usuario

Optimización de red

Optimización de mapa de bits y optimización de compresión de imágenes : Optimización de concurrencia de subprocesos múltiples y optimización de eficiencia de transmisión de datos Optimización de paquetes de volumenhttps://qr18.cn/FVlo89




"Marco de supervisión del rendimiento de Android":https://qr18.cn/FVlo89

"Manual de estudio de Android Framework":https://qr18.cn/AQpN4J

  1. Proceso de inicio de arranque
  2. Inicie el proceso de Zygote en el arranque
  3. Inicie el proceso SystemServer en el arranque
  4. Conductor de carpeta
  5. Proceso de inicio de AMS
  6. El proceso de puesta en marcha del PMS
  7. Proceso de inicio del lanzador
  8. Los cuatro componentes principales de Android
  9. Servicio del sistema Android: proceso de distribución del evento de entrada
  10. Análisis del código fuente del mecanismo de actualización de la pantalla de representación subyacente de Android
  11. Análisis del código fuente de Android en la práctica

Supongo que te gusta

Origin blog.csdn.net/weixin_61845324/article/details/132351467
Recomendado
Clasificación