android 优化布局的三种形式

本文介绍了三种Android布局优化方法:使用include简化重复布局、merge减少视图层级及ViewStub按需加载布局。通过具体实例展示了如何应用这些技巧提升用户体验。

这几天看了一些优化布局的材料,感觉,使用 include merge ViewStub会很好的增强代码的可读性,和观赏性,很大程度的优化了我们自己的布局,下面我写一些自己学到的东西,大家一起学习!

1.首先是include,

在官网上,

The <include /> does exactly what its name suggests; it includes another XML layout. Using this tag is straightforward as shown in the following example, taken straight from the source code of the Home application that currently ships with Android:

<com.android.launcher.Workspace
    android:id="@+id/workspace"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"

    launcher:defaultScreen="1">

    <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
    <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
    <include android:id="@+id/cell3" layout="@layout/workspace_screen" />

</com.android.launcher.Workspace>
include里面包含一些其他的布局文件xml,这只需要以上面的形式写出就可以方便的调用,同时,像例子中的那样可以重复利用一个xml代码,要注意几点:
1.The above example shows that you can use android:id to specify the id of the root view of the included layout; it will also override the id of the included layout if one is defined.如果在workspace_screen布局里面已经有id,而include里面又重新定义了这个id,则会覆盖原来的id
2.This means that any android:layout_* attribute can be used with the <include /> tag.可以使用layout_*的任何属性
2.merge的用法:
<merge/>标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。merge多用于替换FrameLayout或者当一个布局包含另一个时,merge标签消除视图层次结构中多余的视图组。例如你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,

That's where the <merge /> tag comes in handy. When the LayoutInflater encounters this tag, it skips it and adds the<merge /> children to the <merge /> parent. Confused? Let's rewrite our previous XML layout by replacing theFrameLayout with <merge />:

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
    
        android:scaleType="center"
        android:src="@drawable/golden_gate" />
    
    <TextView
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_marginBottom="20dip"
        android:layout_gravity="center_horizontal|bottom"

        android:padding="12dip"
        
        android:background="#AA000000"
        android:textColor="#ffffffff"
        
        android:text="Golden Gate" />

</merge>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge">

    <ImageView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
    
        android:scaleType="center"
        android:src="@drawable/golden_gate" />
    
    <com.example.android.merge.OkCancelBar
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_gravity="bottom"

        android:paddingTop="8dip"
        android:gravity="center_horizontal"
        
        android:background="#AA000000"
        
        okCancelBar:okLabel="Save"
        okCancelBar:cancelLabel="Don't save" />

</merge>

This new layout produces the following result on a device:

Creating a custom view with the merge tag

The source code of OkCancelBar is very simple because the two buttons are defined in an external XML file, loaded using aLayoutInflate. As you can see in the following snippet, the XML layout R.layout.okcancelbar is inflated with theOkCancelBar as the parent:

自定义view,

public class OkCancelBar extends LinearLayout {
    public OkCancelBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(HORIZONTAL);
        setGravity(Gravity.CENTER);
        setWeightSum(1.0f);
        
        LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true);
        
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0);
        
        String text = array.getString(R.styleable.OkCancelBar_okLabel);
        if (text == null) text = "Ok";
        ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);
        
        text = array.getString(R.styleable.OkCancelBar_cancelLabel);
        if (text == null) text = "Cancel";
        ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);
        
        array.recycle();
    }
}

The two buttons are defined in the following XML layout. As you can see, we use the <merge /> tag to add the two buttons directly to the OkCancelBar. Each button is included from the same external XML layout file to make them easier to maintain; we simply override their id:

这两个按钮如下所示,在OkCancelBar里面我们添加了两个按钮,对同一个xml我们重新利用include定义了id

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <include
        layout="@layout/okcancelbar_button"
        android:id="@+id/okcancelbar_ok" />
        
    <include
        layout="@layout/okcancelbar_button"
        android:id="@+id/okcancelbar_cancel" />
</merge> 

The <merge /> tag is extremely useful and can do wonders in your code. However, it suffers from a couple of limitation:

  • <merge /> can only be used as the root tag of an XML layout
  • When inflating a layout starting with a <merge />, you must specify a parent ViewGroup and you must setattachToRoot to true (see the documentation of the inflate() method)
merge标签只能用于xml;当Inflate以merge开头时,必须指定一个父ViewGroup也必须设定attachToRoot为true
3.ViewStub:

To use a ViewStub all you need is to specify an android:id attribute, to later inflate the stub, and an android:layoutattribute, to reference what layout file to include and inflate. A stub lets you use a third attribute, android:inflatedId, which can be used to override the id of the root of the included file. Finally, the layout parameters specified on the stub will be applied to the roof of the included layout. Here is an example:

<ViewStub
  android:id="@+id/stub_import"
  android:inflatedId="@+id/panel_import"

  android:layout="@layout/progress_overlay"

  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_gravity="bottom" />

When you are ready to inflate the stub, simply invoke the inflate() method. You can also simply change the visibility of the stub to VISIBLE or INVISIBLE and the stub will inflate. Note however that the inflate() method has the benefit of returning the root View of the inflate layout:

当你想加载布局时,,可以在下面选用一种方法:

((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();



上面的很多内容来自对谷歌官网的一些摘抄,加入了个人的理解,希望对大家有帮助-_-






Android 开发中,布局优化是提升应用性能和用户体验的重要手段。布局过于复杂或嵌套过深会导致绘制时间变长、内存占用增加、滑动卡顿等问题。以下是 **布局优化三种常见方式**: --- ### 一、减少布局层级(降低 View 树的复杂度) #### 原理: 布局层级越深,系统在测量(measure)和布局(layout)阶段的计算量就越大,导致性能下降。 #### 优化方式: - 使用 `ConstraintLayout` 替代 `LinearLayout` 和 `RelativeLayout`,它可以扁平化布局结构。 - 避免多层嵌套的 `LinearLayout` 或 `RelativeLayout`。 - 使用 `merge` 标签合并布局(适用于 include 的场景)。 - 使用 `ViewStub` 延迟加载某些不常用的 View。 #### 示例: ```xml <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/btn_click" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` --- ### 二、使用布局分析工具(如 Layout Inspector、Hierarchy Viewer) #### 原理: 通过工具分析当前布局的层级结构、渲染时间等信息,找出性能瓶颈。 #### 工具介绍: - **Layout Inspector**:Android Studio 提供,可以实时查看 App 的布局结构和属性。 - **Hierarchy Viewer**:已废弃,但原理仍适用于理解布局层级。 - **Systrace / Perfetto**:用于分析 UI 渲染性能,查看 measure、layout、draw 耗时。 #### 使用建议: - 在开发阶段定期使用 Layout Inspector 检查布局层级。 - 对比优化前后的布局深度和渲染时间。 --- ### 三、避免过度绘制(Overdraw) #### 原理: 过度绘制是指屏幕上的某个像素在同一帧内被多次绘制,造成 GPU 资源浪费。 #### 优化方式: - 移除不必要的背景色或重复的背景设置。 - 减少层级中重复的透明或半透明 View。 - 使用 `android:clipToPadding="false"` 控制绘制区域。 - 利用 GPU 渲染模式分析工具查看过度绘制区域。 #### 工具检测: - 打开开发者选项中的 **"Show GPU Overdraw"**: - 通过颜色判断过度绘制程度(从蓝、绿、粉、红依次加重)。 --- ### 总结对比: | 优化方式 | 优点 | 工具支持 | 适用场景 | |----------|------|----------|----------| | 减少布局层级 | 提升 measure/layout 性能 | Layout Inspector | 复杂界面、嵌套布局 | | 使用布局分析工具 | 定位性能瓶颈 | Android Studio | 开发调试阶段 | | 避免过度绘制 | 减少 GPU 负载 | GPU Overdraw、Systrace | 界面卡顿、渲染慢 | ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值