Android开发优化技巧

1.布局优化
为什么?
Android系统每个16ms发出VSYNC信号,触发对UI的渲染,要想达到界面流畅,必须实现60fps,也就意味着大多数的操作必须在16ms完成.
除了上面界面过于复杂导致渲染不能及时完成之外,还存在过度绘制问题.所谓过度绘制就是某个像素在同一帧的时间内被绘制多次.在多层次的UI界面中,如果不可见的UI也在进行绘制,那么这些重合区域的像素就会被绘制多次,从而浪费大量的CPU和GPU资源.过度绘制也发生在背景重叠的情况下,比如Layout中有自己的背景,同时子View中又有自己的背景.
如何检测?
使用HierarchyViewer来查找Activity中的布局是否过于复杂
在开发者选项中打开Show GPU Overdraw选项进行观察是否存在过度绘制
在开发者选项中选择Profile GPU Rendering,选中On screen as bar
使用TraceView来观察CPU执行情况

如何优化?
减少布局的层级,合理的使用include,merge,ViewStub
自定义组件的onDraw()中避免大量创建临时对象,比如String,以免频繁触发GC
自定义组件的onDraw()中,考虑使用canvas.clipRect()绘制需要被绘制的区域
对像ListView这样的组件容器,考虑使用convertView,使用ViewHolder,
考虑使用性能更高的组件,比如推荐使用RecycleView来代替ListView,使用staticlayout来实现自动换行

2.内存优化
为什么?
资源总是有限的,内存同样也是一种资源.在Android当中,过度的/不恰当占用内存资源,会导致应用频繁被杀死,最终也会影响用户的整体体验.任何一名开发者,都应该将节省内存牢记心中.
如何检测?
使用LeakCanary
使用MAT分析Java堆
使用Android Device Monitor中的Application Tracker追踪内存分配信息
Android Studio中的Android Monitor,选择其中的Memory

如何优化?
主动的释放内存,在onLowMemory()和onTrimMemory()中适当的释放内存

避免内存泄漏和内存溢出

在使用Bitmap的时候,考虑对其进行压缩,使用缓存或者改变颜色模式,比如android默认的颜色格式是ARGB_8888,在要求不高的情况下可以采用RGB__565,这样每个像素占用的内存就可懂4byte到2byte.

减少帧动画的使用,如果需要,通过SurfaceView实现

使用更轻量级的数据结构,比如ArrayMap/SparseArray

合理的使用相关组件,比如Service和Webview,在不需要的时候主动结束其生命周期

合理的使用多进程,比如像音乐播放器类,可以分为主进程和播放进程

使用异步队列时考虑有界队列

如果你能明确知道HashMap的大小,那就再初始化时为其制定容量

3.电量优化
为什么?
电量是移动设备非常宝贵的资源,作为一名开发者,有必要为用户着想,减少电量的消耗.调查显示通常只有30%左右的电量是被程序核心的功能所消耗,比如界面渲染,剩下的70%则是被上报数据,位置更新,后台通知所消耗.
如何检测?
手机选项中通过查看APP的电量消耗的统计数据
使用Battery Historian Tool来查看详细的电量消耗

如何优化?
减少唤醒屏幕的次数与持续的时间,正确的使用WakeLock.
延迟非必须的操作到充电状态时,比如日志上报完全可以在夜间充电时完成,这点可以结合JobScheduler使用
使用传感器采集数据时,一旦不需要记得取消注册.
减少网络通信,合并通信.
合理使用定位功能,减少位置更新频率以及根据实际情况使用不同精度的定位需求

4.网络优化
为什么?
现在App几乎都需要联网操作,做好网络优化一方面可以提高体验,另一方面可以减少流量和电量的损耗.另外,无论是对用户还是网络服务提供者,网络同样是一种资源,任何开发者都不应该假设网络资源是无限制的.
如何检测?
使用Android Studio里的Network Traffic Tools来查看网络请求
使用Android Studio中的Monitor
使用Fidder或者Charles等抓包工具分析网络数据包

如何优化?
有必要的时候务必做好缓存,无论是图片还是普通的数据,使用LruCache和DiskLruCache构建自己的缓存系统,并根据实际场景设计缓存策略
避免过度的网络同步,合并相关的网络请求
根据实际场景确定请求策略,避免使用固定的间隔频率来进行网络操作.比如连接WiFi并充电的情况下请求频率可以高,第一次网络请求失败后可以使用双倍的时间间隔来进行下一次
减少数据传输量,对传输的数据做压缩.如果传输的是图片,需要选择合适的图片格式以及根据显示大小请求合适规格的图片.对于普通数据,可以考虑使用ProtocalBuffers来减小传输数据的大小.
某些情况下可以采用IP直连,一方面可以减少DNS解析时间,另一方面可以防止域名劫持

5.启动优化
为什么?
启动优化看起来并不是那么必要,但从心理学角度而言,越快的启动速度往往给用户以性能好,高效可靠的心理暗示,这就很容易让用户对其产生好感,为你后面打动用户留下了余地.
如何检测?
使用Method Tracing
使用Systrace,比如在onCreate中添加trace.beginSection()和trace.endSection()
使用adb shell am start -W [packageName]/[packageName.MainActivity]
测量冷启动时间

如何优化?
Activity的onCreate()中减少复杂和耗时的操作
Application的onCreate(),attachBaseContext()中同样减少复杂和耗时的操作,但是对于很多App在此处会执行大量组件和服务的初始化操作,如果可能考虑并行初始化
提供自定义启动窗口,比如将一张图片通过设置主题的方式显示为启动窗口.
优化布局

6.体积优化
为什么?
对用户而言,无论是用户空间还是网络,亦或是时间,都是资源.体积优化就是为用户节省资源的重要一环.如果你现在做的是SDK类产品,那么体积优化同样重要.
如何检测?
使用Android Lint检查没有使用的资源

如何优化?
减少不必要的依赖库/Jar,在满足需求的前提下优先选择体积小的.
使用Proguard工具进行代码瘦身,优化,混淆
减少so文件的数量,根据实际情况提供so文件
使用Gradle中的shrinkResource来将无用的代码和资源排除在APK安装包之外
减少图片资源的大小,考虑图片压缩或者使用Vertor Drawable替代png/jpeg
有选择的提供对应分辨率的图片资源
复用已经存在的图片,多用通过代码对已有图片进行变换的方式实现复用
使用插件化技术(如果项目简单就不要使用)

7.性能优化
能发挥出100%的能力就不要只发挥其中的50%,这对应用而言并非坏事.同样的价格卖给用户两辆车,我想大多数人会选择性能更好的.
如何检测?
使用Lint执行静态分析,在Android Studio的Analysis->Inspect Code
在开发者选项中开启StrictMode或者在代码中开启
代码Review

如何优化?
任务并行化,对可能的任务进行并行操作,多借助线程池而非直接使用线程
如何需要序列化数据,优先考虑Android自身提供的而非Java提供的Serializable
选择合适的数据结构,明确List/Set/Map/Stack操作的复杂度
使用Android提供更高效的容器,比如使用ArrayMap来代替HashMap,此外还是有SparseBoolMap,SparseIntMap,SparseLongMap
使用静态常量代替Enum类型,可以减少至少两倍的内存消耗
使用对象池技术,比如提供想String一样的对象池
使用缓存技术
字符串拼接操作有限使用StringBuilder
对相关的算法和逻辑进行优化,减少不必要的流程
采用JNI,对计算量较大的逻辑将其协程so文件,如图片处理

业务优化
除了上述比较通用的优化方案之外,也应该花点时间放在业务优化上.很多时候,迫于时间压迫,当前实现业务的方案并非最优.比如为了支持多张图片上传,很多人直接使用串行操作,尽管这样做容易实现,但是却并非最佳.
由于每个产品的业务并不相同,也就很难有通用的优化方案,这里又两个目标值得思考:
如果有可能,串行业务并行化
如果有可能,简化业务流程.将一大象关进冰箱的方法就是打开冰箱,将大象放进去,最后关闭冰箱.

之所以把业务优化放在最后的根本原因是业务优化的风险较高,需要团队的整体配合来完成.
Android中图片有四种颜色格式
默认的是ARGB_8888,其中ARGB分别代表的是透明度,红色,绿色,蓝色,每个值分别用8位来记录,也就是一个像素会占用4byte,共32位.
而ARGB_4444和以上很类似,但是每个值分别用4位来记录,也就是一个像素会占用2byte,共16位.
RGB_565则分别用5位,6位,5位来记录每个值,不存在透明度,每个像素会占用2byte,共16位.
ALPHA_8:该像素只保存透明度,会占用1byte,共8位.
在实际应用中而言,值推荐使用ARGB_8888以及RGB_565,如果你不需要透明度,那么就选择RGB_565,可以减少一半的内存占用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容