Android中XML布局文件的使用非常频繁,在加载XML布局的时候,如果对XML文件其进行优化,将会提高加载的效率。
再开始介绍之前先说一下HierarchyViewer工具的使用。
不合理的布局会使我们的应用程序UI性能变慢,HierarchyViewer能够可视化的角度直观地获得UI布局设计结构和各种属性的信息,帮助我们优化布局设计。HierarchyViewer是我们优化程序的工具之一,它是Android自带的非常有用的工具,可以帮助我们更好地检视和设计用户界面(UI),绝对是UI检视的利器。
使用:http://blog.csdn.net/xyz_lmn/article/details/14222975
在android加载XML布局文件,创建View或者ViewGroup的时候,XML文件的布局的深度和广度都会对这个过程造成影响。因此XML文件布局的深度和广度都会使创建View的过程更加的耗时,尤其是在布局文件多层嵌套的情况下,因此我们在进行布局的时候,应该尽量考虑使用扁平化的结构,减少布局的深度和复杂性。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demon.com.xmloptimization.MainActivity">
<ImageView
android:id="@+id/icon1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
<ImageView
android:id="@+id/icon2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/icon1"
android:src="@mipmap/ic_launcher_round"/>
<ImageView
android:id="@+id/icon3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/icon2"
android:layout_below="@+id/icon2"
android:src="@mipmap/ic_launcher_round"/>
RelativeLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="demon.com.xmloptimization.MainActivity">
<ImageView
android:id="@+id/icon1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/icon2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
<ImageView
android:id="@+id/icon3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
LinearLayout>
LinearLayout>
对比可知道明显使用LinearLayout比使用RelativeLayout多一层结构,更加耗时。
在应用的多个界面中,经常会有几个界面存在相同或者类似的部分,例如标题栏,导航栏之类的。这些重复的界面如果一一写下来,既浪费时间精力,又不方便统一管理,例如需要改动的时候,在这种情况下,可以把这个重复的界面布局独立出来,然后通过include标签,将这个布局导入需要引用的地方,这样就可以只维护这个独立出来的布局文件即可。
我们将一个ImageView独立写出来:
layout.xml:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round">
ImageView>
使用include:
activity_main.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demon.com.xmloptimization.MainActivity">
<include layout="@layout/layout"/>
<include
layout="@layout/layout"/>
<include layout="@layout/layout"/>
LinearLayout>
merge标签可以用来代替布局文件中的根节点,例如LinearLayout,RelativeLayout,FrameLayout等元素。配合include标签,可以减少布局的嵌套。例如:
layout.xml:
<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>
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demon.com.xmloptimization.MainActivity">
<include layout="@layout/layout"/>
<include
layout="@layout/layout"/>
LinearLayout>
效果:
使用include标签将以上布局复用的时候,将会直接把两个Button放在include标签的位置,而不会再使用其他容器来包装这两个Button,这样就会减少不必要的嵌套,有利于布局的扁平化。
在实际应用中,可能存在一部分界面是处于隐藏状态的,在一定的条件下,才会展示出来。我们一般会将这部分节目使用setVisibility(View.GONE)方法将其隐藏起来,但是我们更推荐使用ViewStub来达到相同的目的。因为ViewStub是一个处于不可见状态的View,初始状态时不会被加载出来,不会浪费资源,而处于View.GONE状态的View也是需要被加载的。ViewStub的使用方法类似include标签,需要在其中声明需要加载的布局文件。
layout.xml:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round">
ImageView>
activity_main.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demon.com.xmloptimization.MainActivity">
<ViewStub
android:id="@+id/viewstub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/layout"/>
<include
layout="@layout/layout"/>
LinearLayout>
public class MainActivity extends AppCompatActivity {
private View view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (view != null) {
view.setVisibility(View.VISIBLE);
return;
}
ViewStub viewStub = (ViewStub) findViewById(R.id.viewstub);
view = viewStub.inflate();
}
}
ViewStub viewStub = (ViewStub) findViewById(R.id.viewstub);
viewStub.setVisibility(View.VISIBLE);
对于inflate的布局可以直接缓存,用全部变量代替局部变量,避免下次需再次inflate。
如上代码中:
if (view != null) {
view.setVisibility(View.VISIBLE);
return;
}
再如LsitView中常见的:
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
……
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
(1) 用SurfaceView或TextureView代替普通View
SurfaceView或TextureView可以通过将绘图操作移动到另一个单独线程上提高性能。
普通View的绘制过程都是在主线程(UI线程)中完成,如果某些绘图操作影响性能就不好优化了,这时我们可以考虑使用SurfaceView和TextureView,他们的绘图操作发生在UI线程之外的另一个线程上。
因为SurfaceView在常规视图系统之外,所以无法像常规试图一样移动、缩放或旋转一个SurfaceView。TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外,还可以像常规视图一样被改变。
(2) 使用RenderJavascript
RenderScript是Adnroid3.0引进的用来在Android上写高性能代码的一种语言,语法给予C语言的C99标准,他的结构是独立的,所以不需要为不同的CPU或者GPU定制代码代码。
(3) 使用OpenGL绘图
Android支持使用OpenGL API的高性能绘图,这是Android可用的最高级的绘图机制,在游戏类对性能要求较高的应用中得到广泛使用。
Android 4.3最大的改变,就是支持OpenGL ES 3.0。相比2.0,3.0有更多的缓冲区对象、增加了新的着色语言、增加多纹理支持等等,将为Android游戏带来更出色的视觉体验。
(4) 尽量为所有分辨率创建资源
减少不必要的硬件缩放,这会降低UI的绘制速度,可借助Android asset studio
http://www.trinea.cn/android/layout-performance/
http://blog.csdn.net/u010483016/article/details/46042721