Android性能优化
2016-07-24 18:27
316 查看
最近在看《开发艺术探索》,写的很棒的一本书,大家有时间可以看看,今天再次看了一下 Android性能优化。
Android的内存和CPU的使用都受到了限制,不能像PC机那样使用内存和CPU ,过多的使用内存会造成OOM(内存溢出);过多的使用CPU资源,即执行大型的耗时任务,会造成程序卡顿,甚至会发生ANR(程序无响应),因此,Android的性能问题在编程时很重要。下面介绍一些Android性能优化的方法,有一些我也理解的不透彻。
一.布局优化
我们知道android的界面很多都是布局层级的嵌套,即View树,在写XML文件时,要做到布局优化,就要尽量减少布局层级,这样View在绘制过程中的工作量就会减少。
首先避免写布局中的无用控件和层级,再者,选择相对效率高的布局,比如,可以用RelativeLayout 也可以用 LinearLayout ,在层级相同的情况下,选择LinearLayout ,因为RelativeLayout 的布局过程较复杂。
布局的优化还有以下三种:
(1)使用<include>标签
作用:将指定的布局文件加载到当前布局文件,举个例子:
如果还要制定其他的属性 , include只支持layout_开头的属性,还有 id,如下面所示
(2)使用<merge>标签
<merge>标签一般和<include>一起使用,见很少布局的层级,比如,当前布局是一个水平方向的LinearLayout ,其内部也包含一个竖直方向的LinearLayout ,那么就可以通过<merge>标签去掉多余的内部布局文件。
(3)ViewStub
作用:在需要的时候加载所需的布局文件,本身不参与任何的布局和绘制过程
注意:不支持<merge>标签
ViewStub是继承自View,
它的使用场景,比如网络异常时的界面,这个没有必要再整个界面初始化的时候将其加载进来,即可用ViewStub。
如下所示,android:id是ViewStub的id,而android:inflatedId是布局的根元素的id。
二,绘制优化
绘制优化是指View的onDraw方法要避免执行大量的操作:
在onDraw中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁的gc,降低了程序的执行效率。
onDraw方法中不要指定耗时任务,也不能执行成千上万次的循环操作,View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms,虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法的复杂度总是切实有效的。
三,内存泄漏优化
(1)静态变量导致
(2)单例模式导致 因为单例模式的生命周期和Application保持一致。
(3)属性动画 比如动画一直在播放
四,响应速度优化和ANR日志分析
ANR出现的情况:Activity如果5秒内没有响应屏幕触摸事件或者键盘输入事件就会ANR。而BroadcastReceiver如果10s没有执行完操作也会出现ANR。
当一个进程发生了ANR之后,系统会在/data/anr目录下创建一个文件traces.txt,通过分析这个文件就能定位ANR的原因。
五,ListView和Bitmap优化
ListView优化:采用ViewHolder并避免在getView方法中执行耗时操作;根据列表的滑动状态来绘制任务的执行效率;可以尝试开启硬件加速期来使ListView的滑动更加流畅。
Bitmap优化:根据需要对图片进行采样,主要是通过BitmapFactory.Options来根据需要对图片进行采样,采样主要用到了BitmapFactory.Options的inSampleSize参数。
六,线程优化
采用线程池,避免程序中存在大量的Thread。线程池可以重用内部的线程,从而避免了线程的创建和销毁所带来的性能开销,同时线程池还能有效的控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生。
关于性能优化的一些注意点:
避免 创建过多的对象
不要过多的使用枚举,枚举占用的内存空间要比整形大
常量请用static final来修饰
使用一些Android特有的数据结构,比如SparseArray和Pair等,它们都具有更好的性能
适当使用软引用和弱引用
采用内存缓存和磁盘缓存
尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄漏
对于内存泄漏那块,是有分析工具MAT,可以试着测试一下自己的项目,看一下有没有内存泄漏。
如有不足之处,请多多指教。
Android的内存和CPU的使用都受到了限制,不能像PC机那样使用内存和CPU ,过多的使用内存会造成OOM(内存溢出);过多的使用CPU资源,即执行大型的耗时任务,会造成程序卡顿,甚至会发生ANR(程序无响应),因此,Android的性能问题在编程时很重要。下面介绍一些Android性能优化的方法,有一些我也理解的不透彻。
一.布局优化
我们知道android的界面很多都是布局层级的嵌套,即View树,在写XML文件时,要做到布局优化,就要尽量减少布局层级,这样View在绘制过程中的工作量就会减少。
首先避免写布局中的无用控件和层级,再者,选择相对效率高的布局,比如,可以用RelativeLayout 也可以用 LinearLayout ,在层级相同的情况下,选择LinearLayout ,因为RelativeLayout 的布局过程较复杂。
布局的优化还有以下三种:
(1)使用<include>标签
作用:将指定的布局文件加载到当前布局文件,举个例子:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/titlebar"/> </LinearLayout>
如果还要制定其他的属性 , include只支持layout_开头的属性,还有 id,如下面所示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <include android:id="@+id/new_title" android:layout_width="match_parent" android:layout_height="match_parent" layout="@layout/titlebar"/> </LinearLayout>其他的属性,比如background 这些,在titlebar.xml文件中实现即可。
(2)使用<merge>标签
<merge>标签一般和<include>一起使用,见很少布局的层级,比如,当前布局是一个水平方向的LinearLayout ,其内部也包含一个竖直方向的LinearLayout ,那么就可以通过<merge>标签去掉多余的内部布局文件。
(3)ViewStub
作用:在需要的时候加载所需的布局文件,本身不参与任何的布局和绘制过程
注意:不支持<merge>标签
ViewStub是继承自View,
它的使用场景,比如网络异常时的界面,这个没有必要再整个界面初始化的时候将其加载进来,即可用ViewStub。
如下所示,android:id是ViewStub的id,而android:inflatedId是布局的根元素的id。
<ViewStub android:id="@+id/xxx" android:inflatedId="@+id/yyy" android:layout="@layout/zzz" ... </ViewStub>需要加载ViewStub中的布局的时候,可以按照如下两种方式进行:
((ViewStub)findViewById(R.id.xx)).setVisibility(View.VISIBLE);或者
View importPanel = ((ViewStub)findViewById(R.id.stub_import)).inflate();
二,绘制优化
绘制优化是指View的onDraw方法要避免执行大量的操作:
在onDraw中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁的gc,降低了程序的执行效率。
onDraw方法中不要指定耗时任务,也不能执行成千上万次的循环操作,View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms,虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法的复杂度总是切实有效的。
三,内存泄漏优化
(1)静态变量导致
(2)单例模式导致 因为单例模式的生命周期和Application保持一致。
(3)属性动画 比如动画一直在播放
四,响应速度优化和ANR日志分析
ANR出现的情况:Activity如果5秒内没有响应屏幕触摸事件或者键盘输入事件就会ANR。而BroadcastReceiver如果10s没有执行完操作也会出现ANR。
当一个进程发生了ANR之后,系统会在/data/anr目录下创建一个文件traces.txt,通过分析这个文件就能定位ANR的原因。
五,ListView和Bitmap优化
ListView优化:采用ViewHolder并避免在getView方法中执行耗时操作;根据列表的滑动状态来绘制任务的执行效率;可以尝试开启硬件加速期来使ListView的滑动更加流畅。
Bitmap优化:根据需要对图片进行采样,主要是通过BitmapFactory.Options来根据需要对图片进行采样,采样主要用到了BitmapFactory.Options的inSampleSize参数。
六,线程优化
采用线程池,避免程序中存在大量的Thread。线程池可以重用内部的线程,从而避免了线程的创建和销毁所带来的性能开销,同时线程池还能有效的控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生。
关于性能优化的一些注意点:
避免 创建过多的对象
不要过多的使用枚举,枚举占用的内存空间要比整形大
常量请用static final来修饰
使用一些Android特有的数据结构,比如SparseArray和Pair等,它们都具有更好的性能
适当使用软引用和弱引用
采用内存缓存和磁盘缓存
尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄漏
对于内存泄漏那块,是有分析工具MAT,可以试着测试一下自己的项目,看一下有没有内存泄漏。
如有不足之处,请多多指教。
相关文章推荐
- Android 补间动画
- Android中的事件分发和处理
- Android之基于位置的服务
- Android使用SeekBar时动态显示进度且随SeekBar一起移动
- Android 自定义Seekbar
- Android 初识Retrofit
- Android 二维码扫描和生成简单实现
- Android 创建带有tab的滑动页面
- Android Studio 配置lambda表达式和rxjava
- Android之广播与服务<一>
- Android/Ios组件名称一览表
- Android 6.0中应用程序使用硬件访问服务实例
- Activity次级页面和主页间来回跳转,防止重复创建Activity实例
- 创建第一个Android项目
- android底层之什么是Zram?
- android如何实现类似ios点击状态栏回到顶部功能
- Android中数据存储
- Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化
- Android Studio: Plugin with id 'android-library' not found
- Android 6.0中添加硬件访问服务