Android布局优化——merge与ViewStub

本文探讨Android布局优化,重点讲解merge标签和ViewStub如何减少控件树层级,提高页面渲染效率。通过HierarchyViewer工具观察布局变化,详细解释merge如何避免额外的FrameLayout,以及ViewStub如何按需加载视图,从而实现优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于Android中的布局优化,主要分为四点。

1.减少控件树的层级

2.include标签的使用

3.merge标签的使用

4.ViewStub视图的使用

看上去有四点,其实总的来说就只有第一点,减少控件树的层级,之后的三点其实就是通过不同的方式来减少控件树的层级,本文重点介绍后两种方式,merge标签的使用,以及ViewStub视图的使用。

我们知道,Android中的布局是通过xml文件实现的,那么xml文件又是如何和activity进行关联的呢?很简单,setContentView嘛,那么setContentView具体执行了什么操作呢,相信大家对这个方法不会感到陌生。

View.inflate(this,R.layout.activity_main,null);

其实setContentView就是将我们的xml文件进行解析,然后根据View的标签和属性实例化对象,加载到对应的父控件中,由此可见,只要减少控件树的层级就等于是减少了实例化对象的数量,也就增加了页面渲染的效率。

在介绍merge和ViewStub之前,我先介绍AndroidStudio下的控件树预览工具——HierarchyViewer

在AndroidStudio下点击如下按钮调出设备管理器

再点击调出HierarchyViewer


那么HierarchyViewer就被启动了,下面就是关于merge和ViewStub的介绍啦

一.merge

新建一个xml布局,代码如下。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.mergeandviewstub.MainActivity"
    android:background="#ffffff"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView"
        android:layout_gravity="left|top" />
</FrameLayout>
很简单的布局,就是一个FrameLayout嵌套一个TextView,现在我们运行一下,看HierarchyViewer所呈现出来的层级图

由上图中的层级关系我们可以看到,在我们的xml文件外还有一个rootView,类型和我们xml中的根视图是一样的,都为FrameLayout,这就满足了我们使用merge标签的

两个重要条件。

1. <merge />只能作为XML布局的根标签使用!

2.xml布局的根视图与contentView的视图类型相同(都为FrameLayout)!

我们来看更改FrameLayout标签后的布局文件

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.mergeandviewstub.MainActivity"
    android:background="#ffffff"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView"
        android:layout_gravity="left|top" />
</merge>
再来看HierarchyViewer中的控件树结构

很明显少了一层FrameLayout,而将TextView直接加到了ContentView的FrameLayout上了。

2.ViewStub

我们在实际的开发中总会遇到这样的情况,在某些情景下,我们需要显示指定的View,在有些情景下,我们又需要隐藏指定的View,假设我们一开始我们将该View隐

藏,这个控件是否会在界面渲染的时候添加到控件树上呢?我们先来试试看。

xml代码

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:visibility="gone"
        android:id="@+id/textView"
        android:layout_gravity="left|top" />
</merge>
如上,我已经TextView的visibility设置为Gone,我们再来看控件树的结构:

如图所示,我们看到TextView依旧被渲染了,可见即使在该View不可见的情况下,在解析xml的标签集合时还是解析到了这个TextView。

下面我们换一种方式,使用ViewStub来控制View的可见与否。

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    >
    <ViewStub
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout="@layout/index"
        />
</merge>
index.xml

<RelativeLayout 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"
        android:textColor="#ffffff"
        />
</RelativeLayout>
现在直接执行,查看控件树的渲染情况。

上图可见,渲染出来的只有一个ViewStub,ViewStub所包含的视图并没有被渲染出来,现在我们让ViewStub的视图变为可见。

public class MainActivity extends AppCompatActivity {
    private ViewStub viewStub;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewStub = (ViewStub)findViewById(R.id.viewstub);
        viewStub.inflate();
        //viewStub.setVisibility(View.VISIBLE);
    }
}
执行viewStub.inflate()和viewStub.setVisibility(View.VISIBLE)都可以达到效果。

控件树。

由此可见,ViewStub被包含着TextView的RelativeLayout所替代了,隐藏的View被展示。

综上所述,不管是include,还是merge,亦或者是ViewStub,都是通过减少控件树的层级来达到布局优化的目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值