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需要进行嵌套才能实现的一些布局,这样对于实现布局的扁平化有更好的效果。

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

Android XML布局文件优化_第1张图片


使用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 Studio 使用Gradle引入第三方库文件的总结
  2. Android中ViewPager+Fragment懒加载问题解决方案Android中ViewPa
  3. Android 虚拟机Dalvik、Android各种java包功能、Android相关文件
  4. 在Android中用纯Java代码布局
  5. android实现横竖屏不间断播放文件
  6. Android mediaplayer 播放本地音乐文件
  7. Android NDK开发(一)——ndk-build编译生成so库文件并使用

随机推荐

  1. android 自定义侧边栏
  2. 查看基于Android(安卓)系统单个进程内存
  3. Building the System Android
  4. ListView美化(2)-android:cacheColorHint
  5. android软键盘挡住输入框问题解决方法
  6. android Log图文详解(Log.v,Log.d,Log.i,
  7. afinal - afinal 是一个android的 orm 和
  8. Android开发之旅:android架构
  9. Android TextView 属性设置
  10. android控件的对齐方式转讲