Análisis del código fuente de las etiquetas de combinación para reducir el secreto de la jerarquía de diseño (Android Q)

Análisis del código fuente de las etiquetas de combinación para reducir el secreto de la jerarquía de diseño (Android Q)


Estoy en "Optimización del rendimiento de renderizado de Android: ¡todo lo que necesita saber!" " También se describen en el artículo las etiquetas de combinación que se utilizan para reducir los niveles. Ver el árbol para optimizar el diseño de Android.

Usamos la etiqueta merge en el diseño para reducir niveles innecesarios.

escenas que se utilizarán

La etiqueta merge puede optimizar el nivel de diseño, entonces, ¿cuáles son sus principales escenarios de uso?

  1. El uso más común de la combinación es con la etiqueta de inclusión. De esta manera, cuando se reutiliza el diseño, no se agregará el anidamiento de diseño redundante y se resuelve el problema causado solo por la etiqueta de inclusión.
  2. Además, al personalizar la Vista combinada (por ejemplo, heredando de FrameLayout, LinearLayout, etc.), generalmente creamos un diseño personalizado y lo agregamos a la Vista personalizada a través del ID de índice. En este momento, si la etiqueta merge no es usado, será invisible. Agregará un nivel de anidamiento.

Por ejemplo, hemos personalizado una Vista de contenedor, el nombre de la clase es TestLayout, heredado de LinearLayout, el diseño de relleno de este control personalizado puede usar la etiqueta merge.

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</merge>

TestLayout hereda de LinearLayout, por lo que es un LinearLayout en sí mismo. Si modificamos la combinación en el diseño a LinearLayout, habrá 2 anidamientos LinearLayout, uno de los cuales es redundante.

Principio de combinación de etiquetas y análisis de código fuente

Entonces, ¿cuál es el principio de reducir el nivel de la etiqueta merge?

Para conocer su principio, la forma más directa es consultar el código fuente de Android. A continuación, analicemos su principio de implementación a través del código fuente.

Al leer el análisis del artículo anterior "Explicación detallada del código fuente de vista generado por LayoutInflater Layout de Android Q" , se puede ver que el objeto de vista generado por el diseño de Android se procesa a través del servicio LayoutInflater, y el método inflar de LayoutInflater es responsable de analizar el diseño y generar objetos de vista. El procesamiento de la etiqueta merge está incluido en este proceso. Veamos el método de inflado de LayoutInflater.

El método de inflado de LayoutInflater

    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            ……
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            ……
            try {
                ……
                //如果根标签是 merge 标签
                if (TAG_MERGE.equals(name)) {
                    //如果根节点是 merge,并且 root 是 null 或者 attachToRoot == false,则抛出异常。
                    if (root == null || !attachToRoot) {
                        throw new InflateException("<merge /> can be used only with a valid "
                                + "ViewGroup root and attachToRoot=true");
                    }
                    //遍历布局并生成View
                    rInflate(parser, root, inflaterContext, attrs, false);
                } else {
                    //非 merge 跟标签,则创建根标签所代表的 View 对象。
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);
                    ViewGroup.LayoutParams params = null;
                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        //获取根标签 View 对象的视图属性,这里会使用根标签所设置的属性来生成属性对象。
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            //对根标签设置它的属性
                            temp.setLayoutParams(params);
                        }
                    }
                    ……

                    //以根标签对象为根,递归遍历它的 xml 子视图。
                    rInflateChildren(parser, temp, attrs, true);
                    ……
                }
            }
        }
    }

Para el archivo de diseño con la etiqueta merge como etiqueta raíz:

  1. Cuando el archivo de diseño de la etiqueta merge se genera como una vista, debe existir root y attachToRoot debe ser verdadero; de lo contrario, se lanzará una excepción InflateException.
  2. A continuación, llame al método rInflate para atravesar las subetiquetas en el diseño y generar View.
  3. Aquí, la raíz (la vista principal del archivo de diseño en el árbol de vistas) y los atributos se pasan al método rInflate para crear una subvista del archivo de diseño.

Para archivos de diseño con una etiqueta que no se fusiona como etiqueta raíz:

  1. Cree el objeto Ver representado por la etiqueta raíz. Esto no se crea en la etiqueta merge, porque merge no es un componente de vista.
  2. Obtenga las propiedades de vista de la etiqueta raíz Objeto de vista, aquí usará las propiedades establecidas por la etiqueta raíz para generar el objeto de propiedad y luego establecerá sus propiedades en la etiqueta raíz. Esto tampoco se ejecuta durante la etiqueta merge, por lo que los atributos establecidos en la etiqueta merge no tendrán efecto.
  3. Tome el objeto de etiqueta raíz como raíz y recorra sus subvistas xml de forma recursiva. Al fusionar la etiqueta, toma raíz como raíz (como parámetro) para atravesar las sub-etiquetas de la etiqueta merge. ¡Este es el secreto detrás de la etiqueta merge!

Método RInflate de LayoutInflater

    void rInflate(XmlPullParser parser, View parent, Context context
            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
        ……
        while (((type = parser.next()) != XmlPullParser.END_TAG ||
                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
            ……
            final String name = parser.getName();

            if (TAG_REQUEST_FOCUS.equals(name)) {
                ……
            } 
            …… ……
            } else if (TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } else {
                final View view = createViewFromTag(parent, name, context, attrs);
                final ViewGroup viewGroup = (ViewGroup) parent;
                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                rInflateChildren(parser, view, attrs, true);
                viewGroup.addView(view, params);
            }
        }
        ……
    }

El propósito de este método es recorrer y crear el objeto del componente Ver representado por la subetiqueta de la etiqueta raíz en el archivo de diseño xml.

  1. El método rInflate analiza de forma recursiva el contenido del archivo de diseño xml, crea una Vista y la agrega al padre.
  2. Tenga en cuenta aquí que la etiqueta merge debe ser el nodo raíz del archivo de diseño.

Bueno, aquí ya conocemos el secreto de la etiqueta merge.

para resumir


Resumamos:

  1. La etiqueta de combinación se puede utilizar para reducir el nivel del árbol de vista y optimizar el diseño de Android.

  2. El objeto de vista generado por el diseño de Android se procesa a través del servicio LayoutInflater. El método inflar de LayoutInflater es responsable de analizar el diseño y generar el objeto de vista.

  3. Al usar la etiqueta merge, la etiqueta merge debe ser el nodo raíz del archivo de diseño.

  4. Cuando el archivo de diseño de la etiqueta merge se genera como una vista, debe existir root y attachToRoot debe ser verdadero; de lo contrario, se lanzará una excepción InflateException.

  5. ¡Los atributos establecidos en la etiqueta merge no son válidos!

  6. Al analizar el archivo de diseño, en circunstancias normales, el objeto de etiqueta raíz se utiliza como raíz y sus subvistas xml se recorren de forma recursiva; cuando se usa la etiqueta merge, la raíz es la raíz (como parámetro) y se pasa al método rInflate para crear una subvista. ¡Este es el secreto detrás de la etiqueta merge!


PD: Para obtener más artículos de análisis, consulte la serie de artículos -> columna "Análisis de los principios subyacentes de Android" .
PD: Para obtener más artículos de análisis, consulte la serie de artículos -> columna "Análisis de los principios subyacentes de Android" .
PD: Para obtener más artículos de análisis, consulte la serie de artículos -> columna "Análisis de los principios subyacentes de Android" .

Supongo que te gusta

Origin blog.csdn.net/u011578734/article/details/111494896
Recomendado
Clasificación