App性能优化主要从以下几方面考虑:

内存, UI,  电量


1. 内存

内存是最重要的一个app性能指标.

首先简单介绍一下Android系统内存管理机制.

内存共享:

Android系统起来后首先启动Zygote进程,并在该进程中加载和运行framework的代码和资源,以及一些Java核心类库.app进程是Zygote进程fork出来的,所有app进程与Zygote进程共享运行framework和Java核心类库的那部分内存.

app内存限制:

Android系统会根据设备物理内存的大小给每个app进程设置固定大小的heap space,超过这个大小就报OOM错误.  

默认情况:String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");只有16m.

可以通过在device.mk文件中设置:PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.heapgrowthlimit=256m

app进程缓存:

Android系统将后台app缓存到一个cache中, 系统在低内存的情况下会根据lru算法杀死部分后台进程.


然后看app内存优化

app内存优化主要从以下几个方法入手;

1) 防止内存泄漏

 内存泄漏的根本原因是不再使用的对象还被gc root直接或者间接引用,导致gc无法回收. 以下地方容易产生内存泄漏:

a. 重写finalize()方法可能会导致内存泄漏

b. 单例模式,单利对象本身就是gc root,它自己和引用的对象不能被gc回收.

c. 尽量使用静态内部类,因为非静态内部类自动持有外部类的引用,容易导致内存泄漏,而静态内部类不持有外部类的引用.

d. 谨慎使用service, 因为service的生命周期往往比activity长,如果service持有activity的引用,容易导致activity无法被回收.

e. 注意关闭资源,BraodcastReceiver,ContentObserver,File,Cursor,Stream等.

2) 防止内存抖动

内存抖动是指频繁的创建对象和回收对象,这样会浪费大量的CPU资源.避免在循环语句和View.onDraw()方法中创建对象.

3) 尽量使用Android优化过的数据类,如pb, SparseArray等.

4) 谨慎处理bitmap,太大就压缩,太多就分页加载,滑动过程中不要加载.建议使用开源框架fresco和Glide.

    如果要显示超级大图,又不能压缩,可以用BitmapRegionDeoder类进行分区域解码显示.


2. UI

Android系统每隔16ms进行一次界面刷新,应用主线程在16ms内不能处理完消息队列里面的任务并完成界面刷新就会导致丢帧,也就是卡顿. 卡顿超过5秒就报ANR.

主要有两种情况会导致卡顿

1. app主线程做了耗时操作

2. app界面过度绘制

过度绘制是指屏幕上某个像素在同一帧的时间内被绘制了多次,这会导致某些像素区域被绘制了多次, 这就浪费了大量的CPU和GPU资源,导致在指定时间无法完成绘制.

针对第一种情况,我们可以将主线程的耗时操作,比如大数据量计算和读写IO等,移到子线程执行即可.

针对第二种情况,主要有以下几种解决方法:

a. 移除不必要的背景图片,包括windows默认背景getWindow().setBackgroundDrawable(null)。

b. 优化布局,减少布局层次,尽量多使用LinearLayout,少使用RelativeLayout,多使用Merge/Include等标签。

c. 在自定义view里面通过canvas.clipRect()指定绘制区域,使用canvas.quickreject()减小绘制区域。


常用性能检查工具StrictMode(严格模式)介绍

严格模式监视那些本不应该在主线程中完成的工作,包括读写I/O,网络访问等,还可以监视内存泄漏问题.

Log打开方法;

首先在应用入口进行设置,然后通过"adb logcat -s StrictMode"命令查看代码中的违规情况.


关于UI有以下几点需要注意:
1. 系统每16ms都会去调用一次view的onDrow()方法,所以在该方法里面尽量不要创建对象,不要使用循环,不要执行耗时操作.
2. app启动之后,ViewRootImpl在每次界面刷新之前都会check线程,如果是子线程发起的请求就报错.
   不能在子线程刷新UI,是因为如果在多个子线程同时刷新UI会导致app不可知异常。而在主线程中由主线程的消息队列统一管理,不会冲突。


3. 电量

电量消耗大户: CPU, 网络和屏幕.这三个方面主要是在网络上做优化.

网络优化方案:

1) 预取网络数据

    预取都是在网络信号激活的情况下进行的,减少了激活网络信号的开销.

2) 压缩传送的数据

3) 本地缓存


google在android6.0上设计了低电耗模式和应用待机模式.在这两种模式下会将后台任务推迟,堆积到一起处理.