Análise de código-fonte de tags de mesclagem para reduzir o segredo da hierarquia de layout (Android Q)
Estou em "Otimização do desempenho de renderização do Android - tudo o que você precisa saber! " Descrito no artigo também, as tags de mesclagem usadas para reduzir os níveis da árvore de visualização para otimizar o layout do Android.
Usamos a tag de mesclagem no layout para reduzir níveis desnecessários.
cenas a serem usadas
A tag de mesclagem pode otimizar o nível de layout, então quais são seus principais cenários de uso?
- O uso mais comum de mesclar é com a tag de inclusão. Dessa forma, quando o layout for reutilizado, o aninhamento de layout redundante não será adicionado e o problema causado apenas pela tag de inclusão será resolvido.
- Além disso, ao personalizar a Visualização combinada (por exemplo, herdar de FrameLayout, LinearLayout, etc.), geralmente criamos um layout personalizado e o adicionamos à Visualização personalizada por meio do id do índice. Neste momento, se a tag de mesclagem não for usado, será invisível. Adicionará um nível de aninhamento.
Por exemplo, personalizamos um container View, o nome da classe é TestLayout, herdado de LinearLayout, o layout de preenchimento deste controle personalizado pode usar a tag de mesclagem.
<?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 herda de LinearLayout, portanto é um LinearLayout em si. Se modificarmos a mesclagem no layout para LinearLayout, haverá 2 aninhamentos LinearLayout, um dos quais é redundante.
Princípio da tag de mesclagem e análise do código-fonte
Então, qual é o princípio de reduzir o nível da tag de mesclagem?
Para conhecer seu princípio, a forma mais direta é verificar o código-fonte do Android. A seguir, vamos analisar seu princípio de implementação por meio do código-fonte.
Ao ler a análise no artigo anterior "Explicação detalhada do código-fonte da visualização gerada do layout do Android Q" , pode-se ver que o objeto da visualização gerado pelo layout do Android é processado por meio do serviço LayoutInflater e o método inflate do LayoutInflater é responsável por analisar o layout e gerar objetos View. O processamento da tag de mesclagem está incluído neste processo. Vejamos o método inflate de LayoutInflater.
O método inflate 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 o arquivo de layout com a tag de mesclagem como a tag raiz:
- Quando o arquivo de layout da tag de mesclagem é gerado como uma visualização, a raiz deve existir e attachToRoot deve ser verdadeiro, caso contrário, uma InflateException será lançada.
- Em seguida, chame o método rInflate para percorrer os sub-rótulos no layout e gerar a visualização.
- Aqui, root (a visão pai do arquivo de layout na árvore de visão) e attrs são passados para o método rInflate para criar uma subvisualização do arquivo de layout.
Para arquivos de layout com uma tag não mesclada como a tag raiz:
- Crie o objeto View representado pelo rótulo raiz. Isso não é criado na tag de mesclagem, porque mesclagem não é um componente de visualização.
- Obtenha as propriedades de visualização do objeto Visualização do rótulo raiz, aqui irá usar as propriedades definidas pelo rótulo raiz para gerar o objeto de propriedade e, em seguida, definir suas propriedades no rótulo raiz. Isso também não é executado durante a tag de mesclagem, portanto, os atributos definidos na tag de mesclagem não terão efeito.
- Pegue o objeto de tag raiz como raiz e percorra suas subvisualizações xml recursivamente. Ao mesclar a tag, ele toma a raiz como raiz (como um parâmetro) para percorrer as submarcas da tag de mesclagem. Este é o segredo por trás da tag de mesclagem!
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);
}
}
……
}
O objetivo deste método é percorrer e criar o objeto de componente View representado pela subtag da tag raiz no arquivo de layout xml.
- O método rInflate analisa recursivamente o conteúdo do arquivo de layout xml, cria uma visualização e a adiciona ao pai.
- Observe aqui que a tag de mesclagem deve ser o nó raiz do arquivo de layout!
Bem, aqui, já sabemos o segredo da tag de mesclagem.
Resumindo
Vamos resumir:
-
A tag de mesclagem pode ser usada para reduzir o nível da árvore de visualização para otimizar o layout do Android.
-
O objeto de exibição gerado pelo layout Android é processado por meio do serviço LayoutInflater. O método inflate de LayoutInflater é responsável por analisar o layout e gerar o objeto Exibir.
-
Ao usar a tag de mesclagem, a tag de mesclagem deve ser o nó raiz do arquivo de layout!
-
Quando o arquivo de layout da tag de mesclagem é gerado como uma visualização, a raiz deve existir e attachToRoot deve ser verdadeiro, caso contrário, uma InflateException será lançada.
-
Os atributos definidos na tag de mesclagem são inválidos!
-
Ao analisar o arquivo de layout, em circunstâncias normais, o objeto de tag raiz é usado como raiz e suas subvisualizações xml são percorridas recursivamente; ao usar a tag de mesclagem, a raiz é a raiz (como um parâmetro) e passada para o método rInflate para criar uma subvisualização. Este é o segredo por trás da tag de mesclagem!
PS: Para mais artigos de análise, verifique a série de artigos -> coluna "Análise dos princípios básicos do Android" .
PS: Para mais artigos de análise, verifique a série de artigos -> coluna "Análise dos princípios básicos do Android" .
PS: Para mais artigos de análise, verifique a série de artigos -> coluna "Análise dos princípios básicos do Android" .