详细介绍安卓布局性能优化之(include 、merge、ViewStub)

简介: 详细介绍安卓布局性能优化之(include 、merge、ViewStub)

我们在日常开发中,我们可能会遇到有很多相似的布局,如果每一个XML文件都写一次,不说麻烦,代码也显得冗余,而且可读性也很差.这时候就需要include 了,本编文章将会介绍include、merge和ViewStub标签的用法供大家学习和参考。


include标签

include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,也是平常我们设计布局时用的最多的


include 官方文档


<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:gravity="center_horizontal"
           android:orientation="vertical"> 
<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="@string/textview"
        android:textSize="24sp"/> <EditText
        android:id="@+id/editText"
        android:hint="@string/divide"
        android:layout_width="300dp"
        android:layout_height="wrap_content"/> </LinearLayout> 
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
    > <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="TextView_Relative"
        android:textSize="24sp"/> <EditText
        android:id="@+id/editText"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:hint="@string/divide"/> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/tb_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="#00f"
    app:theme="@style/AppTheme"
    app:title="这是一个ToolBar"
    app:titleTextColor="@android:color/white"/>

1.2、Activity的XML布局文件调用include标签:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
 <!--测试layout和<include>都设置ID的情况-->
<include
        android:id="@+id/tb_toolbar"
        layout="@layout/include_toolbar"/> 
<!--如果只有单个include 这样写就可以,加载的布局的子View,直接findViewByID就能找到--> 
   <include layout="@layout/include_text"/> 
   <!--如果有多个include,需要添加ID属性--> <include
        android:id="@+id/include_text1"
        layout="@layout/include_text"/> 
<!--这个layout用RelativeLayout 实现-->
 <!--如果要使用layout_margin这样的属性,要同时加上layout_w/h属性,不然没反应--> <include
        android:id="@+id/include_text2"
        layout="@layout/include_text_relative"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="50dp"/>
         </LinearLayout>

1.3、Activity中调用include标签layout中的子View:

 private void initView() { 
 //如果include布局根容器和include标签中的id设置的是不同的值,这里获取的mToolbar值将为null 
 Toolbar mToolbar = (Toolbar) findViewById(R.id.tb_toolbar); setSupportActionBar(mToolbar); 
 //普通include标签用法,直接拿子View属性实现
  TextView textView = (TextView) findViewById(R.id.textView); textView.setText("不加ID实现的include标签"); 
  //多个include标签用法,添加ID,findViewByID找到layout,再找子控件 
  View view_include = findViewById(R.id.include_text1); TextView view_include_textView = (TextView) view_include.findViewById(R.id.textView); view_include_textView.setText("加了ID实现的include标签"); 
  //多个include标签用法,添加ID,findViewByID找到layout,再找子控件
   View view_include_Relative = findViewById(R.id.include_text2); TextView view_textView_relative = (TextView) view_include_Relative.findViewById(R.id.textView); view_textView_relative.setText("加了ID实现的include标签(RelaviteLayout)"); }

include使用注意

一个xml布局文件有多个include标签需要设置ID,才能找到相应子View的控件,否则只能找到第一个include的layout布局,以及该布局的控件

include标签如果使用layout_xx属性,会覆盖被include的xml文件根节点对应的layout_xx属性,建议在include标签调用的布局设置好宽高位置,防止不必要的bug

include 添加id,会覆盖被include的xml文件根节点ID,这里建议include和被include覆盖的xml文件根节点设置同名的ID,不然有可能会报空指针异常

如果要在include标签下使用RelativeLayout,如layout_margin等其他属性,记得要同时设置layout_width和layout_height,不然其它属性会没反应

merge 标签

merge标签主要用于辅助include标签,在使用include后可能导致布局嵌套过多,多余的layout节点或导致解析变慢(可通过hierarchy viewer工具查看布局的嵌套情况)


官方文档说明:merge用于消除视图层次结构中的冗余视图,例如根布局是Linearlayout,那么我们又include一个LinerLayout布局就没意义了,反而会减慢UI加载速度


merge 官方文档


merge标签常用场景:


1.根布局是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一个。

2.某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

3.自定义View如果继承LinearLayout(ViewGroup),建议让自定义View的布局文件根布局设置成merge,这样能少一层结点。


merge标签使用:

在XML布局文件的根布局如RelativeLayout直接改成merge即可


merge使用注意

1.因为merge标签并不是View,所以在通过LayoutInflate.inflate()方法渲染的时候,第二个参数必须指定一个父容器,且第三个参数必须为true,也就是必须为merge下的视图指定一个父亲节点.

2.因为merge不是View,所以对merge标签设置的所有属性都是无效的.

3.注意如果include的layout用了merge,调用include的根布局也使用了merge标签,那么就失去布局的属性了

4.merge标签必须使用在根布局

5.ViewStub标签中的layout布局不能使用merge标签


ViewStub 标签

我们在做安卓项目的时候,经常会有一个使用场景:需要在运行时根据数据动态决定显示或隐藏某个View和布局。

上述场景,我们通常的解决方案就是:就是把可能用到的View先写在布局里,再初始化其可见性都设为View.GONE,然后在代码中根据数据动态的更改它的可见性。

虽然这样的实现,逻辑简单而且控制起来比较灵活;但是也存在一定的缺点耗费资源。

ViewStub 标签最大的优点是当你需要时才会加载,使用它并不会影响UI初始化时的性能.各种不常用的布局像进度条、显示错误消息等可以使用ViewStub标签,以减少内存使用量,加快渲染速度.ViewStub是一个不可见的,实际上是把宽高设置为0的View.效果有点类似普通的view.setVisible(),但性能体验提高不少

第一次初始化时,初始化的是ViewStub View,当我们调用inflate()或setVisibility()后会被remove掉,然后在将其中的layout加到当前view hierarchy中。


先来看看布局,一个是主布局,里面只定义二个ViewStub,一个用来控制TextView一个用来控制ImageView,另外就是一个是为显示文字的做的TextView布局,一个是为ImageView而做的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:gravity="center_horizontal">
  <ViewStub 
    android:id="@+id/viewstub_demo_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dip"
    android:layout_marginRight="5dip"
    android:layout_marginTop="10dip"
    android:layout="@layout/viewstub_demo_text_layout"/>
  <ViewStub 
    android:id="@+id/viewstub_demo_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dip"
    android:layout_marginRight="5dip"
    android:layout="@layout/viewstub_demo_image_layout"/>
</LinearLayout>

为TextView的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content">
        <TextView
            android:id="@+id/viewstub_demo_textview"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#aa664411"
            android:textSize="16sp"/>
    </LinearLayout>

下面来看代码,决定来显示哪一个,只需要找到相应的ViewStub然后调用其infalte()就可以获得相应想要的布局:

    public class ViewStubDemoActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.viewstub_demo_activity);
            if ((((int) (Math.random() * 100)) & 0x01) == 0) {
                // to show text
                // all you have to do is inflate the ViewStub for textview
                ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_text);
                stub.inflate();
                TextView text = (TextView) findViewById(R.id.viewstub_demo_textview);
                text.setText("The tree of liberty must be refreshed from time to time" +
                        " with the blood of patroits and tyrants! Freedom is nothing but " +
                        "a chance to be better!");
            } else {
                // to show image
                // all you have to do is inflate the ViewStub for imageview
                ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_image);
                stub.inflate();
                ImageView image = (ImageView) findViewById(R.id.viewstub_demo_imageview);
                image.setImageResource(R.drawable.happy_running_dog);
            }
        }
    }

ViewStub标签使用注意


ViewStub标签不支持merge标签

ViewStub的inflate只能被调用一次,第二次调用会抛出异常,setVisibility可以被调用多次,但不建议这么做(ViewStub 调用过后,可能被GC掉,再调用setVisibility()会报异常)

为ViewStub赋值的android:layout_XX属性会替换待加载布局文件的根节点对应的属性

扩展:

Space组件

在ConstraintLayout出来前,我们写布局都会使用到大量的margin或padding,但是这种方式可读性会很差,加一个布局嵌套又会损耗性能


鉴于这种情况,我们可以使用space,使用方式和View一样,不过主要用来占位置,不会有任何显示效果



目录
相关文章
|
11月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1045 4
|
1月前
|
存储 消息中间件 人工智能
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
78 11
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
|
1月前
|
XML 存储 Java
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
65 3
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
|
算法 数据处理 Android开发
掌握安卓性能优化的秘诀:电池寿命与运行效率的提升
【10月更文挑战第6天】 本文深入探讨了安卓应用开发中的性能优化技巧,重点分析了影响电池寿命和运行效率的关键因素,并提供了针对性的优化策略。通过代码优化、资源管理、后台任务处理等方法,开发者可以显著提升应用的续航能力和流畅度。同时,结合具体案例,展示了如何在实际开发中应用这些技巧,确保应用在各种场景下都能保持高效运行。本文旨在为安卓开发者提供实用的性能优化指导,助力其打造更优质的应用体验。
314 2
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
172 10
|
12月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
10月前
|
网络协议 Linux Android开发
深入探索Android系统架构与性能优化
本文旨在为读者提供一个全面的视角,以理解Android系统的架构及其关键组件。我们将探讨Android的发展历程、核心特性以及如何通过有效的策略来提升应用的性能和用户体验。本文不包含常规的技术细节,而是聚焦于系统架构层面的深入分析,以及针对开发者的实际优化建议。
297 21
|
11月前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
11月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
178 5
|
11月前
|
缓存 数据库 Android开发
安卓开发中的性能优化技巧
【10月更文挑战第29天】在移动应用的海洋中,性能是船只能否破浪前行的关键。本文将深入探讨安卓开发中的性能优化策略,从代码层面到系统层面,揭示如何让应用运行得更快、更流畅。我们将以实际案例和最佳实践为灯塔,引领开发者避开性能瓶颈的暗礁。
265 3

热门文章

最新文章