Android app性能优化

app性能主要从以下几方面考虑:
内存,CPU(响应),电池。

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
1.内存
内存是最重要的一个app性能指标。
1)android内存管理机制
共享内存
1>android系统起来后会启动Zygote进程,并在该进程中运行framework的code和res,app进程是由Zygote进程fork出来的,所有app进程与Zygote进程共享运行framework的那部分内存。
大多数static数据是共享的,包括:Dalvik code;app resources;native code in .so files.
2>app内存限制
android系统会根据设备物理内存的大小给每个app设置固定大小的heap space,超过这个大小会导致OutOfMemoryError.可以通过ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
int mem = am.getMemoryClass(); 获得当前app所拥有的heap space.
3>app进程缓存
android系统会将后台app缓存到in a least-recently used (LRU) cache中,系统在低内存的情况下会根据lru算法杀死部分进程。

2)app内存优化方法
1>Release memory in response to events
activity可以通过执行ComponentCallbacks2并重写public void onTrimMemory(int level)方法来释放内存。系统会在内存有压力的时候通过该接口将不同的内存紧急等级通知到app进程。
2>谨慎使用Services
使用Services的app不会被系统回收,所以尽量少用,一定要用就用IntentService,因为其执行完任务后会自动finish。
3>多使用优化的容器
HashMap每个mapping都有一个独立的object,效率低。多使用经google优化过的SparseArray, SparseBooleanArray和LongSparseArray。
4>使用protocol buffers替代xml
5>避免内存抖动
内存抖动会频繁触发gc,gc的时候app运行暂停,导致app卡顿。避免在循环语句中创建对象,避免在onDraw()中创建bitmap和Paint.
6>减少大体积类库的使用

静态对象自身和其所持有的对象是不会被gc回收的。

BitMap处理
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
如果图片像素过大,使用BitmapFactory类的方法实例化Bitmap的过程中,就会发生OutOfMemory异常。
使用BitmapFactory.Options设置inSampleSize就可以缩小图片。属性值inSampleSize表示缩略图大小为原始图片大小的几分之一。即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片的大小就为原始大小的1/4。
如果知道图片的像素过大,就可以对其进行缩小。那么如何才知道图片过大呢?
使用BitmapFactory.Options设置inJustDecodeBounds为true后,再使用decodeFile()等方法,并不会真正的分配空间,即解码出来的Bitmap为null,但是可计算出原始图片的宽度和高度,即options.outWidth和options.outHeight。通过这两个值,就可以知道图片是否过大了。
先获取图片真实的宽度和高度,然后判断是否需要跑缩小。如果不需要缩小,设置inSampleSize的值为1。如果需要缩小,则动态计算并设置inSampleSize的值,对图片进行缩小。

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


3)anroid系统给app分配的内存
默认情况:String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");只有16m
可以通过在device.mk文件中设置:PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.heapgrowthlimit=256m

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
2.CPU(响应)
分为启动速度和启动后界面响应两部分
1)启动速度
启动分为冷起,热起和温启动。冷启动是指后台无此进程,需要系统重新创建进程;热启动是指后台有进程,只需要显示到前台即可,不需要调用activity的onCreate(),如按HOME键后退出显示;温启动是指后台有进程,但需要调用
activity的onCreate()方法,如按back键退出应用后。热启动和温启动一搬都很快,我们不用关注。这里只研究冷启动。
<1>冷启动过程
系统将app加载到内存中
系统显示空白Window
系统创建app进程
app进程创建应用的application
app进程启动主线程
app进程创建main activity
app进程填充并绘制视图
第一个界面被显示出来标志启动结束。
可通过activity.reportFullyDrawn()方法打印启动时间,最终在ActivityRecord的reportFullyDrawnLocked()方法中实现。

优化方案:
1.在application和mainActivity的onCreate()方法里面不要执行耗时操作,可以懒加载模式,及先加载当前需要显示的数据,不需要显示的数据放在后面加载。
2.减少xml文件的布局层次,单起线程初始化资源。

2)界面响应
主线程在16ms内不能处理完消息队列里面的任务就会导致界面卡顿。不能在子线程刷新UI,是因为如果在多个子线程同时刷新UI会导致app不可知异常。而在主线程中由主线程的消息队列统一管理,不会冲突。
Activity与线程
Activity启动线程后,在Activity销毁之前先判断线程是为了执行完耗时操作后更新UI,则未无用线程,需要停止。若只是执行一些有益的后台任务,如下载,则不需要停止。不停止无用线程会导致资源的浪费。
优化UI
1>移除不必要的背景图片
2>减少layout层次
3>多使用Merge/Include和标签

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
3.电池
电池消耗大户:CPU,网络和屏幕。这三个方面主要是在网络上做优化。
网络优化方案:
1>预取网络数据
预取都是在网络信号激活的情况下进行的,减少了激活网络信号的开销。
2>压缩传送的数据
3>本地缓存

另外,google在android6.0上设计了低电耗模式和应用待机模式。在这两种模式下会将后台任务推迟,堆积到一起处理。在应用需要需要服务器交互的时候,google 建议使用GCM。

posted @ 2016-12-01 14:12  Tao.Xu  阅读(132)  评论(0)    收藏  举报