前言:
1.android设备作为一种移动设备,不管是内存还是CPU的性能都受到了一定的限制,无法做到PC设备那样具有超大的内存和高性能的CPU,所以,andorid程序不可能无限制地使用内存和CPU资源;
2.过多的使用CPU资源,一般是指做大量的耗时任务,会导致手机变得卡顿甚至程序无法响应的情况,即ANR;过多的使用内存会导致程序内存溢出,即OOM;
3.性能优化中有一个很重要的问题就是内存泄漏,内存泄漏不会导致程序功能异常,但是它会导致android程序的内存占用过大,这将提高内存溢出的发生几率。如何避免写出内存泄漏的代码,甚至有些时候内存泄漏的原因是很难直接发现的,这时需要借助内存泄露分析工具MAT。
正文:
1.布局优化:
它的优化思想就是尽量减少布局文件的层级,布局中的层级少了,意味着android绘制时的工作量少了,那么程序的性能自然就提高了;
如何进行布局优化呢?有几种方案,一是删除布局中无用的控件和层级;
其次是有选择地使用性能较低的ViewGroup,如RelativeLayout;如果布局中既可以使用LinearLayout也可以使用RelativeLayout,那么就采用LinearLayout,因为RelativeLayout的功能比较复杂,它的布局过程需要花费更多的CPU时间;
FrameLayout和LinearLayout一样都是一种简单高效的ViewGroup,如果很多时候单纯的使用一个LinearLayout或者一个FrameLayout无法实现产品效果,需要通过嵌套的方法来完成时,这种情况下还是建议采用RelativeLayout,因为ViewGroup的嵌套就相当于增加了布局的层级,同样会降低程序的性能。
布局优化的另一种手段是采用<include>标签,<merge>标签和ViewStub;
①<include>标签
<include>主要是用于布局重用;
<merge>标签一般和<include>一起配合使用,可以降低减少布局的层级;
ViewStub提供了按需加载的功能,当需要它时才会将ViewStub中的布局加载到内存,提供了程序的初始化效率;
<include>,它可以将一个指定的布局文件加载到当前的布局文件中;该标签只支持以android:layout_开头的属性,如andorid:layout_width,其他属性不支持,如andorid:background。当然,andorid:id这个属性是特例,如果<include>指定了这个id属性,同时被包含的文件的根元素也指定了id属性,那么以<include>指定的id属性为准。
注意:如果<include>指定了android:layout_*这种属性,那么要求android:layout_width和android_layout_height必须存在,否则其他的android:layout_*形式的属性无法生效;
②<merge>标签
该标签一般和<include>一起使用,可以减少布局的层级;
它表示,如果被包含的布局与当前布局是同一个ViewGroup,那么显然被包含的布局文件的ViewGroup是多余的,通过<merge>标签便可以去掉多余的那一层的ViewGroup;即被包含布局的直接父控件和被包含布局的根控件是相同的ViewGroup,被包含布局文件的根控件就可以用<merge>代替;
③ViewStub
ViewStub它继承了View,它是轻量级别的且宽高都是0;因此它本身不参与任何的布局和绘制过程;
它的意义在于按需加载所需的布局文件,在实际开发中,有很多布局文件在正常情况下不需要显示,比如网络绘制时的界面,这个时候就没有必要再整个界面初始化的时候将其加载进来,通过ViewStub就可以做到在使用的时候再加载,提高程序初始化时的性能;
使用方法有两种,一是:(ViewStub)findViewById(R.id.stub_import).setVisibility(View.VISIBLE);另一种是((ViewStub)findViewById(R.id.stub_import)).inflate();
当ViewStub通过setVisibility或者inflate方法加载后,ViewStub就会被它内部的布局替换掉,这个时候ViewStub就不再是整个布局结构中的一部分了。另外,ViewStub目前还不支持<merge>标签
2.绘制优化
它指的是view的onDraw方法要避免执行大量的操作,这个主要体现在两方面。
首先onDraw中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,不仅占用了过多的内存而且还会导致系统更加频繁的GC,降低了程序的执行效率;
另外,onDraw方法中不要做耗时的任务,也不能执行成千上万次的循环操作,因为大量的循环会抢占CPU的时间片,会造成view的绘制过程不流畅。
按照google官方给出的性能优化典范中的标准,view的绘制帧率保证60fps是最佳的,虽然很难保证,但是尽量降低onDraw方法的复杂度;