Android布局优化

Posted yl007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android布局优化相关的知识,希望对你有一定的参考价值。

android影响布局性能主要是Overdraw(过度绘制),表现在重叠不可见元素的重复绘制会产生额外的开销。

Overdraw以颜色划分等级:蓝色:Overdraw1倍;绿色:Overdraw2倍;浅红:Overdraw3倍;暗红;Overdraw4倍以上(需要进行优化)。

Android布局优化解决措施:

1、合理选择控件

  LinearLayout简单易用,效率高,但是使用范围有限。

  RelativeLayout较复杂,使用范围广,效率稍差。

2、去掉windows默认背景

  去掉window的背景可以在onCreate()中setContentView()之后调用 getWindow().setBackgroundDrawable(null);或者在theme中添加android:windowbackground="null";

3、去掉不必要的背景

  如果子View宽度mach_parent,可以看到完全覆盖了Layout的一部分,这里就可以通过分别设置背景来减少重绘。再比如如果采用的是selector的背景,将normal状态的color设置为“@android:color/transparent",也同样可以解决问题。

4、ClipRect & QuickReject

  我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,那些部分内容在矩形区域内的组件,仍然会得到绘制。除了clipRect方法之外,我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。

5、ViewStub(高效占位符)
  ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。
<ViewStub
    android:id="@+id/stub_view"
    android:inflatedId="@+id/panel_stub"
    android:layout="@layout/progress_overlay"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom" />

当你想加载布局时,可以使用下面其中一种方法:

((ViewStub) findViewById(R.id.stub_view)).setVisibility(View.VISIBLE);
View importPanel = ((ViewStub) findViewById(R.id.stub_view)).inflate();

6、Merge

  作用:干掉一个VIew层级。

  有两种情况下我们可以使用Merge标签来做容器控件。第一种子视图不需要指定任何针对父视图的布局属性,就是说父容器仅仅是个容器,子视图只需要直接添加到父视图上用于显示就行。另外一种是假如需要在LinearLayout里面嵌入一个布局(或者视图),而恰恰这个布局(或者视图)的根节点也是LinearLayout,这样就多了一层没有用的嵌套,无疑这样只会拖慢程序速度。而这个时候如果我们使用merge根标签就可以避免那样的问题。另外Merge只能作为XML布局的根标签使用,当Inflate以<merge />开头的布局文件时,必须指定一个父ViewGroup,并且必须设定attachToRoot为true。

7、善用draw9patch
  给ImageView加一个边框,你肯定遇到过这种需求,通常在ImageView后面设置一张背景图,露出边框便完美解决问题,此时这个ImageView,设置了两层drawable,底下一层仅仅是为了作为图片的边框而已。但是两层drawable的重叠区域去绘制了两次,导致overdraw。
优化方案: 将背景drawable制作成draw9patch,并且将和前景重叠的部分设置为透明。由于Android的2D渲染器会优化draw9patch中的透明区域,从而优化了这次overdraw。 但是背景图片必须制作成draw9patch才行,因为Android 2D渲染器只对draw9patch有这个优化,否则,一张普通的Png,就算你把中间的部分设置成透明,也不会减少这次overdraw。
 
8、慎用Alpha
  假如对一个View做Alpha转化,需要先将View绘制出来,然后做Alpha转化,最后将转换后的效果绘制在界面上。通俗点说,做Alpha转化就需要对当前View绘制两遍,可想而知,绘制效率会大打折扣,耗时会翻倍,所以Alpha还是慎用。
  如果一定做Alpha转化的话,可以采用缓存的方式。
view.setLayerType(LAYER_TYPE_HARDWARE);
doSmoeThing();
view.setLayerType(LAYER_TYPE_NONE);

通过setLayerType方式可以将当前界面缓存在GPU中,这样不需要每次绘制原始界面,但是GPU内存是相当宝贵的,所以用完要马上释放掉。

9、避免“OverDesign”

 

参考文献:http://www.jianshu.com/p/145fc61011cd

以上是关于Android布局优化的主要内容,如果未能解决你的问题,请参考以下文章

Android获取片段中的布局高度和宽度

如何在android中的地图片段内中心线性布局?

iOS 相当于 Android 片段/布局

带有两个列表片段的可滚动布局

在Android中,如何将数据从类传递到相应的布局/片段文件?

android布局片段和普通布局