Android性能优化

布局优化

Android UI渲染机制

在Android中,系统通过VSYNC信号触发对UI的渲染、重绘,其间隔时间是16ms。15 = 1000/60(1秒内显示60帧画面的单位时间)。

Android系统提供了检测UI渲染时间的工具,打开“开发者选项”,选择“Profile GPU Rendering”,并选中“On screen as bars”的选项,这时候在屏幕上将显示一个条形图。

蓝色代表测量绘制Display List的时间,红色代表OpenGL渲染DIsplay List所需要的时间,黄色代表CPU等待GPU处理的时间。中间的绿色横线代表VSYNC时间16ms,需要尽量将所有条形图都控制在这条绿线之下。

避免Overdraw

Android系统在开发者选项中提供了这样一个检测工具——“Enable GPU Overdraw”。激活后,可以通过界面上的颜色来判断Overdraw的次数。尽量优化绘图层次,尽量增大蓝色的区域,减少红色区域。

优化布局层级

在Android中,系统对View进行测量、布局和绘制时,都是通过对View数的遍历来进行操作的。如果一个View树的高度太高,就会严重影响测量、布局和绘制的速度。Google建议View树的高度不宜超过10层。

避免嵌套过多无用布局

嵌套的布局会让View树的高度变得越来越高,因此在布局时,需要根据自身布局的特点来选择不同的Layout组件,从而避免通过某一种Layout组件来实现功能时的局限性,从而造成嵌套过多的情况发生。

使用标签重用Layout

使用实现View的延迟加载

<ViewStub
    android:layout="@layout/***"
    ...
>

在代码中如何使用呢?

mViewStub = (ViewStub)findViewById(R.id.***);

通过调用ViewStub的setVisibility()方法来显示这个View,代码如下所示:

mViewStub.setVisibility(View.VISIBLE);

或者通过调用ViewStub的inflate()方法来显示这个View,代码如下:

View inflateView = mViewStub.inflate();

标签与设置View.GONE这种方式来隐藏这个View有什么区别?

共同点都是初始时不会显示,但是标签只会在显示时,才去渲染整个布局,而View.GONE,在初始化布局树的时候就已经添加到布局树上了,相比之下标签的布局具有更高的效率。

Hierarchy Viewer

内存优化

什么是内存?

内存是指手机的RAM,它包括以下几个部分:

栈:

存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中。

堆:

堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器(GC)来管理。

静态存储区域(Static Field)

静态存储区域就是指在固定的位置存放应用程序运行时一直存放的数据,Java在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量。

常量池:

JVM虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型,字段和方法的符号引用。

在程序中,可以使用如下代码来获得堆的大小,所谓的内存分析,正是分析Heap中的内存状态。

ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);

int heapSize = manager.getLargeMemoryClass();

获取系统内存信息

Process Stats

Process Stats是一个系统内存监视服务,可以通过“Setting-Developer options——Process Stats”来开启功能的界面。

同样,也可以使用Dumpsys命令来获取这些信息。

adb shell dumpsys procstats

Meminfo

Meminfo也是系统上的一个非常重要的内存监视工具,可以通过在Settings——Apps——Running中打开这一界面。

也可以使用Dumpsys命令。

adb shell dumpsys meminfo

内存优化实例

Bitmap优化

  1. 使用适当分辨率和大小的图片
  2. 及时回收内存(及时调用bitmap.recycle()方法释放内存资源)
  3. 使用图片缓存(通过内存缓存(LruCache)和硬盘缓存(DiskLruCache))

代码优化

  1. 对常量使用static修饰符;
  2. 使用静态方法,静态方法会比普通方法提高15%左右的访问速度;
  3. 减少不必要的成员变量,在AndroidLint工具已经集成检测,如果一个变量可以定义为局部变量,则建议不要定义为成员变量;
  4. 减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时避免频繁创建短作用域的变量;
  5. 尽量不要使用枚举,少用迭代器;
  6. 对Cursor、Receiver、Sensor、File等对象,要注意对它们的创建,回收与注册,解注册;
  7. 使用RenderScript、OpenGL来进行非常复杂的绘图操作;
  8. 使用SurfaceView来代替View进行大量、频繁得绘图操作;
  9. 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图。

Lint工具

养成写完代码后检查Lint提示的习惯,这不仅可以让你及时发现google代码中隐藏的一些问题,更能让你养成良好的代码风格。

使用Android Studio的Memory Monitor工具

使用TraceView工具优化APP性能

TraceView是一个Android下的可视化性能调查工具,用来分析TraceView日志。

生成TraceView日志的两种方法

通过代码生成精确范围内的TraceView日志

使用Debug类的方法开启TraceView监听。通过调用Debug.startMethodTracing()方法开启监听,通过调用Debug.stopMethodTracing()方法结束监听,通过这两个方法来包围要监听的代码块。

TraceView的日志会保存在”/sdcard/dmtrace.trace”目录下,因此,需要在Mainifest文件中增加如下所示的权限:

<uses-permission 
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>

通过Android Device Monitor生成TraceView日志

在Android Studio的Android Device Monitor工具,选择要调试的进程,点击工具栏的”start method profiling”按钮。

TraceView提供了以下两种监听方式:

  1. 整体监听
  2. 抽样监听

traceView

一般要重点查看占用时间长,而且调用次数少的方法。

使用Mat

这个比较简单,就不说了。

使用Dumpsys命令分析系统状态

使用Dumpsys命令可以列出Android系统相关的信息和服务状态。

使用Dumpsys命令时,只需要输入“adb shell dumpsys + 参数”即可。常用的如下:

activity:显示所有的Activity的栈信息
meminfo:内存信息
battery:电池信息
package:包信息
wifi:显示wifi信息
alarm:显示alarm信息
procstats:显示内存信息

配合Linux下的shell命令,如“grep”,“find”,让该命令发挥作用。