Android中XML布局文件的使用非常频繁,在加载XML布局的时候,如果对XML文件其进行优化,将会提高加载的效率,为我们带来更好的体验。我在这里对一些常见的优化方法进行一下小结,以作为记录。

1.扁平化布局

在Android加载XML布局文件,创建View或者ViewGroup的时候,XML文件的布局的深度和广度都会对这个过程造成影响,具体请参考

 http://lishoubo.github.io/2013/08/12/android-measure-procedure/   android measure procedure  ,这篇博客对该过程作了详细的解读。因此XML文件布局的深度和广度都会使创建View的过程更加的耗时,尤其是在布局文件多层嵌套的情况下,因此我们在进行布局的时候,应该尽量考虑使用扁平化的结构,减少布局的深度和复杂性。

常见情况下我们会使用LinearLayout和RelativeLayout以及FrameLayout,在Android 4.0以后,系统默认使用RelativeLayout作为布局文件的顶层节点,因为其能更准确的获知其中View的位置和大小,相对而言,LinearLayout则需要多次进行测量布局操作,才能获取到正确的信息。RelativeLayout可以更加方便地实现一些LinearLayout需要进行嵌套才能实现的一些布局,这样对于实现布局的扁平化有更好的效果。

例如要实现下面的布局效果


使用LinearLayout的代码如下:

<?xml version="1.0" encoding="utf-8"?>

使用RelativeLayout的代码如下:

<?xml version="1.0" encoding="utf-8"?>

通过比较可以看出,使用RelativeLayout的情况下,可以减少一个LinearLayout的使用,使得所有的ImageView控件都处于同一个层级,降低了布局结构的深度,在使用该布局创建View的时候,可以提高效率。这种情况是一种很常见的情形,也非常的简单,我们随手就可以做到。坚持这种做法,并在更复杂的布局中使用这一原则,一定会收到更好的效果。

同样,我们可以减少布局中不必要的控件的使用,以达到精简布局的效果。例如通过为TextView设置图片,来替换ImageView与TextView的组合,实现同样的效果,而这样只使用了一个控件。还有其他一些小技巧,例如使用HTML标签优化TextView显示,可以参考 http://blog.csdn.net/ljtyzhr/article/details/42402043

2.include标签的使用

在应用的多个界面中,经常会有几个界面存在相同或者类似的部分,例如标题栏,导航栏之类的。这些重复的界面如果一一写下来,既浪费时间精力,又不方便统一管理,例如需要改动的时候,在这种情况下,可以把这个重复的界面布局独立出来,然后通过include标签,将这个布局导入需要引用的地方,这样就可以只维护这个独立出来的布局文件即可。

假设这是一个可供复用的独立布局文件,文件名为titlebar.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width=”match_parent”    android:layout_height="wrap_content"    android:background="@color/titlebar_bg">    <ImageView android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:src="@drawable/gafricalogo" />FrameLayout>
然后你就可以在需要引入这部分布局的文件中,通过include标签,导入这部分布局。
<include layout="@layout/titlebar"/>

<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>
然后titlebar.xml中的布局就替换了include标签位置的部分。

在使用include标签的时候需要注意:

可以复写所有layout属性(任何android:layout_*属性),但是必须同时复写layout_width和 layout_height属性,这些复写的layout属性才会生效。例如:

<include android:id="@+id/news_title"         android:layout_width="match_parent"         android:layout_height="match_parent"         layout="@layout/title"/>

你也可以在include标签中给这个布局定义一个id,这样将会覆盖其独立布局文件中的id值。在声明独立布局中的子View的时候,需要先

FrameLayout titleView  =  findViewById(R.id.new_title);

然后再在titleView中使用  titleView.findViewById() 方法,直接使用findViewById将无法找到其中的子View。


3.merge标签的使用

merge标签可以用来代替布局文件中的根节点,例如LinearLayout,RelativeLayout,FrameLayout等元素。配合include标签,可以减少布局的嵌套。例如

<merge xmlns:android="http://schemas.android.com/apk/res/android">    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/add"/>    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/delete"/>merge>
使用include标签将以上布局复用的时候,将会直接把两个Button放在include标签的位置,而不会再使用其他容器来包装这两个Button,这样就会减少不必要的嵌套,有利于布局的扁平化。


4.ViewStub使用

在实际应用中,可能存在一部分界面是处于隐藏状态的,在一定的条件下,才会展示出来。我们一般会将这部分节目使用setVisibility(View.GONE)方法将其隐藏起来,但是我们更推荐使用ViewStub来达到相同的目的。因为ViewStub是一个处于不可见状态的View,初始状态时不会被加载出来,不会浪费资源,而处于View.GONE状态的View也是需要被加载的。ViewStub的使用方法类似include标签,需要在其中声明需要加载的布局文件

  my_comment_layout布局如下:   

<?xml version="1.0" encoding="utf-8"?>    
在需要加载这部分布局的时候,可以通过两种方式实现加载:

通过setVisibility(View.VISIBLE)的方式,这时候可以通过判断其可见性来得知其是否已经加载  

// 方式1,获取ViewStub,          ViewStub listStub = (ViewStub) findViewById(R.id.stub_import);          // 加载评论列表布局          listStub.setVisibility(View.VISIBLE);          // 获取到评论ListView,注意这里是通过ViewStub的inflatedId来获取              ListView commLv = findViewById(R.id.stub_comm_lv);                  if ( listStub.getVisibility() == View.VISIBLE ) {                         // 已经加载, 否则还没有加载                  }              } 

通过inflate方法来实现加载。注意此时无法通过判断可见性来判断是否已经加载了,可以通过判断其中的元素是否存在来判断加载情况。

 // 把commLv2设置为类的成员变量      ListView commLv2 = null;      //      public void onCreate(Bundle b){          // main.xml中包含上面的ViewStub          setContentView(R.layout.main);          // 方式二          ViewStub listStub2 = (ViewStub) findViewById(R.id.stub_import) ;          // 成员变量commLv2为空则代表未加载          if ( commLv2 == null ) {          // 加载评论列表布局, 并且获取评论ListView,inflate函数直接返回ListView对象            commLv2 = (ListView)listStub2.inflate();          } else {          // ViewStub已经加载          }      } 
需要注意的是,如果ViewStub设置了inflatedId,那么将需要通过该id来查找布局的根元素。

详细讲解请阅读 http://www.codeceo.com/article/android-viewstub-include-merge.html


5.hierarchy viewer工具的使用


6.其他优化

参考:

http://www.codeceo.com/article/android-viewstub-include-merge.html

未完待续

更多相关文章

  1. android The project target (Android(安卓)2.3.3) was not prop
  2. Android(安卓)am 指令的使用
  3. Android滚动多TAB悬浮头效果
  4. [原创]Android中LocationManager的简单使用,获取当前位置
  5. Android学习:资源管理
  6. Android中App可分配内存的大小
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. StevGuo系列文章翻译之没有USB驱动的情况
  2. 轻量级Android6.0动态权限解决方案
  3. Kindle File占美国Android平板出货量54.4
  4. Android查缺补漏之Toolbar
  5. 下载Eclipse想做Android项目配置ADT后关
  6. Android sdk自带的9patch工具(9妹)
  7. Android4.1 无预览拍照
  8. android如何制作出一个简单的聊天app
  9. Android绘图必杀技---Canvas和Drawables
  10. 向大家推荐小专栏《Android 面试指南》,还