Android优化那些事
http://blog.csdn.net/myfriend0/article/details/54970455
目前在公司接触的项目,已经趋于稳定,即需求已经不是那么频繁变更。之前因为快速迭代开发的模块
暴露出一些问题来。优化是目前最重要的任务了。自己挖的坑,含着泪也要填完。因为开发的是系统app,
公司对所有app的性能要求极为严格。毕竟品质是公司的生命线。经历了一个多月的优化工作,总结下都
做了那些事情。
一 代码方面:
1.1 清除所有不用的组件
service,activity,receiver,虽然这些不用的组件占用不了多少存储,但是让代码整体结构更加清晰。
如果不做这样的清理,会让后面维护的同事维护成本变大,后面同事只敢添加代码,不敢轻易删除,最后代码结构变得越来越复杂。
1.2 apk瘦身
因为apk经历了好几次改版,每次改版都会添加不同的资源文件,适配不同分辨率,每次都是往res文件夹下添加各种资源文件,之前几版废弃的资源
都没有删除,有时候因为不知道其它地方是否调用,就不轻易删了,结果导致整个apk的体积变得非常大。当清理了这些不用资源后,结果发下整个
apk体积减少了三分之一,非常吃惊。一个apk里面占用存储最多的就是这些资源文件了。。。
二 业务方面
1.病毒扫描每次扫描时会从进程A中的settingsprovider中读取一些配置信息,之前的逻辑是每次扫描时都会跨进程访问,现在改为一天访问一次
既满足当前功能模块的需求,也避免了频繁跨进程访问进程A.做到按需访问。
2.病毒扫描UI模块和功能模块分别运行在两个进程中,UI模块跨进程调用功能模块,功能模块会返回结果到UI模块。设计两个进程相互通信,
这两个进程各自挂了都会对方有影响,所以在UI进程中对功能进程挂了做了处理,即在onServiceDisConnected()中注册了对功能进程的死亡监听
同时在功能进程也注册了了UI进程的死亡监听,即实现了DeathRecipient接口。这个通信进程彼此监听对方的状态,做好异常情况的处理。
3.SharedPreferences优化
阻塞UI进程,引起ANR
4.PackageInfo缓存优化
提高读取PackageInfo信息速度
三 性能方面
1.App启动优化
App启动的三种方式:
冷启动
App没有启动过或App进程被killed, 系统中不存在该App进程, 此时启动App即为冷启动.
冷启动的流程即为第2节所描述的App启动流程的全过程, 需要创建App进程, 加载相关资源, 启动Main Thread, 初始化首屏Activity等.
热启动
热启动意味着你的App进程只是处于后台, 系统只是将其从后台带到前台, 展示给用户.
温启动
介于冷启动和热启动之间, 一般来说在以下两种情况下发生:
用户back退出了App, 然后又启动. App进程可能还在运行, 但是activity需要重建.
用户退出App后, 系统可能由于内存原因将App杀死, 进程和activity都需要重启, 但是可以在onCreate中将被动杀死锁保存的状态(saved instance state)恢复.
2.优化点
根据冷启动的时间图, 可以看出, 对于App来说, 我们可以控制的启动时间线的点无外乎:
(1)Application的onCreate
(2)首屏Activity的渲染
而我们现在的App动不动集成了很多第三方服务, 启动时需要检查广告, 注册状态等等一系列接口都是在Application的onCreate或是首屏Activity的onCreate中做的.
3.如何定位问题
1.在onCreate开始和结尾打上trace
Debug.startMethodTracing("GithubApp");...Debug.stopMethodTracing();
生成trace文件,使用DDMS去分析耗时的方法
2.最笨的方法,给可疑的方法打印时间戳,定位是那个方法比较耗时
4.怎么优化
拆分onCreate中那些比较耗时但是在onCreate后面不用的初始化工作,放在工作线程中去做。
布局优化
1.问题
布局中经常出现层级较深的问题,这样会导致出现一些过度绘制的问题,从而导致卡顿等
2.问题检测
2.1 Hierarchy Viewer
2.2 Lint tool
Lint tool可以对布局文件中的字体大小,过度使用的布局,contentDescription等等进行检查,然后指导优化
3.问题优化
基本原则:
尽量减少布局层级和复杂度
尽量不要嵌套使用RelativeLayout.(RelativeLayout会让子View调用2次onMeasure)
尽量不要在嵌套的LinearLayout中都使用weight属性.(LinearLayout 在有weight时,也会调用子View2次onMeasure)
Layout的选择, 以尽量减少View树的层级为主.
去除不必要的父布局.
善用TextView的Drawable减少布局层级
如果H Viewer查看层级超过5层, 你就需要考虑优化下布局了~
善用Tag
1. 使用include来重用布局.
标签可以允许在一个布局当中引入另外一个布局,那么比如说我们程序的所有界面都有一个公共的部分,这个时候最好的做法就是将这个公共的部分提取到一个独立的布局文件当中,
然后在每个界面的布局文件当中来引用这个公共的布局。同时在标签当中,我们是可以覆写所有layout属性的,即include中指定的layout属性将会覆盖掉titlebar中指定的layout属性。
2.
标签是作为标签的一种辅助扩展来使用的,它的主要作用是为了防止在引用布局文件时产生多余的布局嵌套。
android:id="@+id/ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="OK" />
android:id="@+id/cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:text="Cancel" />
使用merge引入的布局不会增加新的冗余布局
3. 按需加载布局
一个布局中的部分UI是按照特定的场景需求加载出来的,我们虽然可以将不常用的元素使用INVISIBLE或者GONE进行隐藏来实现相关布局
但是这种实现是会影响性能的,因为在解析布局的时候也会将这些隐藏的元素一一解析出来。使用ViewStub可以按需加载
4.ListView优化,adapter中常用的基本原则:
contentView复用
引入holder来避免重复的findViewById.
分页加载
二 性能方面
一般来说, 有以下几个方面:
App启动优化
布局优化
响应优化
内存优化
电池使用优化
网络优化
1.App启动优化
App启动方式:leng