• 布局优化: <include />、<merge /> 、<ViewStub /> 标签的使用


    在布局优化中,Androi的官方提到了这三种布局<include />、<merge />、<ViewStub />,并介绍了这三种布局各有的优势,下面也是简单说一下他们的优势,以及怎么使用,记下来权当做笔记。

    1. <include />

    <include />标签能够重用布局文件,简单的使用如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width=”match_parent”
        android:layout_height=”match_parent”
        android:background="@color/app_bg"
        android:gravity="center_horizontal">
     
        <include layout="@layout/titlebar"/>
     
        <TextView android:layout_width=”match_parent”
                  android:layout_height="wrap_content"
                  android:text="@string/hello"
                  android:padding="10dp" />
     
    </LinearLayout>

    Note:

    • <include />标签可以使用单独的layout属性,这个也是必须使用的。
    • 可以使用其他属性。<include />标签若指定了ID属性,而你的layout也定义了ID,则你的layout的ID会被覆盖,解决方案

    2. <merge />

    <merge/>标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。<merge/>多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。例如你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用<merge/>标签优化。

    例:

    不使用<merge />

    layout1.xml

    <FrameLayout>
       <include layout="@layout/layout2"/>
    </FrameLayout>

    layout2.xml:

    <FrameLayout>
       <TextView />
    </FrameLayout>

    实际效果

    <FrameLayout>
       <FrameLayout>
          <TextView />
       </FrameLayout>
    </FrameLayout>

    使用 <merge /> 后:

    layout1.xml

    <FrameLayout>
       <include layout="@layout/layout2"/>
    </FrameLayout>

    layout2.xml:

    <merge>
       <TextView />
    </merge>

    实际效果:

    <FrameLayout>
       <TextView />
    </FrameLayout>

    Note:

    • merge必须放在布局文件的根节点上。
    • merge并不是一个ViewGroup,也不是一个View,它相当于声明了一些视图,等待被添加。
    • 因为merge不是View,所以对merge标签设置的所有属性都是无效的。

    3. <ViewSub />

    <ViewStub> 标签实质上是一个宽高都为 0 的不可见 View. 通过延迟加载布局的方式优化布局提升渲染性能.这里的延迟加载是指初始化时, 程序无需显示该标签所指向的布局文件, 只有在特定的条件下, 所指向的布局文件才需要被渲染, 且此布局文件直接将当前<ViewStub> 替换掉. 但这里的替换并不是完全意义上的替换, 布局文件的 layout params 是以 ViewStub 为优先.当初次渲染布局文件时, ViewStub 控件虽然也占据内存, 但是相比于其他控件, 它所占内存很小. 它主要是作为一个“占位符”, 放置于 View Tree中, 且它本身是不可见的。

    应用场景:

    • 网络请求失败的提示
    • 列表为空的提示
    • 新内容、新功能的引导, 因为引导基本上只显示一次
    • 又或者我们写了一个通用的自定义 View. 但其中部分子 View 只在部分情况下才显示.

    使用方式:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:orientation="vertical"
        tools:context=".MergeIncludeViewSubTagActivity">
    
        <ViewStub
            android:id="@+id/view_loading_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout="@layout/viewsub_loading"
            android:layout_gravity="center"
            />
    
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Show ProgressBar"
            android:textAllCaps="false"
            android:onClick="showProgressBar"
            />
    
    </LinearLayout>

    调用时:

    package com.yongdaimi.android.androidapitest;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewStub;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MergeIncludeViewSubTagActivity extends AppCompatActivity {
    
    
        private View loadingView;
    
        public static final String TAG = "xp.chen";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_merge_include_view_sub_tag);
        }
    
    
        public void showProgressBar(View view) {
            if (loadingView == null) {
                ViewStub loadingViewSub = findViewById(R.id.view_loading_view);
                loadingView = loadingViewSub.inflate();
                // 初次使用时调用inflate()方法只是去加载,但并不显示
                loadingView.setVisibility(View.VISIBLE);
            } else {
                if (loadingView.getVisibility() == View.GONE) {
                    loadingView.setVisibility(View.VISIBLE);
                } else {
                    loadingView.setVisibility(View.GONE);
                }
            }
            Log.i(TAG, "loadingView.getVisibility(): "+loadingView.getVisibility());
        }
    
    
    }

    Note:

    • inflate()方法只能被调用一次,多次调用inflate()操作会报错: ViewStub must have a non-null ViewGroup viewParent 
    • 首次调用inflate方法加载完之后,还要手动调用调用setVisibility()方法才能令其显示。

    参考链接:

    1. Android 抽象布局 —— include 、merge 、Viewusb
    2. Android 布局优化Merge的使用

  • 相关阅读:
    WTL介绍
    创业创意
    VelocityTracker简单介绍
    strip 命令的使用方法
    CFileDialog的使用方法简单介绍
    讨论oracle在rowid和rownum
    java entry
    24点经典算法
    char与byte差异
    蓝牙设计
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/11865247.html
Copyright © 2020-2023  润新知