本文来自于腾讯bugly开发者社区,非经做者赞成,请勿转载,原文地址:http://dev.qq.com/topic/580d9...html
这里是Android性能优化典范第6季的课程学习笔记,从被@知会到有连载更新,这篇学习笔记就一直被惦记着,如今学习记录分享一下,请多多指教包涵!此次一共才6个小段落,涉及的内容主要有:程序启动时间性能优化的三个方面:优化activity的建立过程,优化application对象的启动过程,正确使用启动显屏达到优化程序启动性能的目的。另外还介绍了减小安装包大小的checklist以及如何使用VectorDrawable来减小安装包的大小。android
提升程序的启动速度意义重大,很显然,启动时间越短,用户才越有耐心等待打开这个APP进行使用,反之启动时间越长,用户则越有可能来不及等到APP打开就已经切换到其余APP了。程序启动过程当中的那些复杂错误的操做极可能致使严重的性能问题。Android系统会根据用户的操做行为调整程序的显示策略,用来提升程序的显示性能。例如,一旦用户点击桌面图标,Android系统会当即显示一个启动窗口,这个窗口会一直保持显示直到画面中的元素成功加载并绘制完第一帧。这种行为常见于程序的冷启动,或者程序的热启动场景(程序从后台被唤起或者从其余APP界面切换回来)。那么关键的问题是,用户极可能会由于从启动窗口到显示画面的过程耗时过长而感到厌烦,从而致使用户没有来得及等程序启动完毕就切换到其余APP了。更严重的是,若是启动时间过长,可能致使程序出现ANR。咱们应该避免出现这两种糟糕的状况。git
从技术角度来讲,当用户点击桌面图标开始,系统会当即为这个APP建立独立的专属进程,而后显示启动窗口,直到APP在本身的进程里面完成了程序的建立以及主线程完成了Activity的初始化显示操做,再而后系统进程就会把启动窗口替换成APP的显示窗口。github
上述流程里面的绝大多数步骤都是由系统控制的,通常来讲不会出现什么问题,但是对于启动速度,咱们可以控制而且须要特别关注的地方主要有三处:性能优化
Activity的onCreate流程,特别是UI的布局与渲染操做,若是布局过于复杂极可能致使严重的启动性能问题。微信
Application的onCreate流程,对于大型的APP来讲,一般会在这里作大量的通用组件的初始化操做。网络
目前有部分APP会提供自定义的启动窗口,这里能够作成品牌宣传界面或者是给用户提供一种程序已经启动的视觉效果。app
在正式着手解决问题以前,咱们须要掌握一套正确测量评估启动性能的方法。所幸的是,Android系统有提供一些工具来帮助咱们定位问题。异步
首先是display time:从Android KitKat版本开始,Logcat中会输出从程序启动到某个Activity显示到画面上所花费的时间。这个方法比较适合测量程序的启动时间。函数
其次是reportFullyDrawn方法:咱们一般来讲会使用异步懒加载的方式来提高程序画面的显示速度,这一般会致使的一个问题是,程序画面已经显示,但是内容却还在加载中。为了衡量这些异步加载资源所耗费的时间,咱们能够在异步加载完毕以后调用activity.reportFullyDrawn()
方法来告诉系统此时的状态,以便获取整个加载的耗时。
而后是Method Tracing:前面两个方法提供了启动耗时的总时间,但是却没法提供具体的耗时细节。为了获取具体的耗时分布状况,咱们可使用Method Tracing工具来进行详细的测量。
最后是Systrace:咱们能够在onCreate方法里面添加trace.beginSection()与trace.endSection()方法来声明须要跟踪的起止位置,系统会帮忙统计中间经历过的函数调用耗时,并输出报表。
提高Activity的建立速度是优化APP启动速度的首要关注目标。从桌面点击APP图标启动应用开始,程序会显示一个启动窗口等待Activity的建立加载完毕再进行显示。在Activity的建立加载过程当中,会执行不少的操做,例如设置页面的主题,初始化页面的布局,加载图片,获取网络数据,读写Preference等等。
上述操做的任何一个环节出现性能问题均可能致使画面不能及时显示,影响了程序的启动速度。上一个段落咱们介绍了使用Method Tracing来发现那些耗时占比相对较多的方法。假设咱们发现某个方法执行时间过长,接下去就可使用Systrace来帮忙定位究竟是什么缘由致使那个方法执行时间过长。
除了使用工具进行具体定位分析性能问题以外,如下两点经验能够帮助咱们对Activity启动作性能优化:
优化布局耗时:一个布局层级越深,里面包含须要加载的元素越多,就会耗费更多的初始化时间。关于布局性能的优化,这里就不展开描述了!
异步延迟加载:一开始只初始化最须要的布局,异步加载图片,非当即须要的组件能够作延迟加载。
在Application初始化的地方作太多繁重的事情是可能致使严重启动性能问题的元凶之一。Application里面的初始化操做不结束,其余任意的程序操做都没法进行。
有时候,咱们会一股脑的把绝大多数全局组件的初始化操做都放在Application的onCreate里面,但其实不少组件是须要作区队对待的,有些能够作延迟加载,有些能够放到其余的地方作初始化操做,特别须要留意包含Disk IO操做,网络访问等严重耗时的任务,他们会严重阻塞程序的启动。
优化这些问题的解决方案是作延迟加载,能够在application里面作延迟加载,也能够把一些初始化的操做延迟到组件真正被调用到的时候再作加载。
启动闪屏不只仅能够做为品牌宣传页,还可以减轻用户对启动耗时的感知,可是若是使用不恰当,将拔苗助长。前面介绍过当点击桌面图标启动APP的时候,程序会显示一个启动窗口,一直到页面的渲染加载完毕。若是程序的启动速度足够快,咱们看的闪屏窗口停留显示的时间则会很短,可是当程序启动速度偏慢的时候,这个启动闪屏能够必定程度上减轻用户等待的焦虑感,避免用户过于轻易的关闭应用。
目前大多数开发者都会经过设置启动窗口主题的方式来替换系统默认的启动窗口,经过这种方式只是使用『障眼法』弱化了用户对启动时间的感知,但本质上并无对启动速度作什么优化。也有些APP经过关闭启动窗口属性android:windowDisablePreview
的方式来直接移除系统默认的启动窗口,可是这样的弊端是用户从点击桌面图标到真的看到实际页面的这段时间当中,画面没有任何变化,这样的用户体验是十分糟糕的!
对于启动闪屏,正确的使用方法是自定义一张图片,把这张图片经过设置主题的方式显示为启动闪屏,代码执行到主页面的onCreate的时候设置为程序正常的主题。
减小应用程序安装包的大小,不只仅减小了用户的网络数据流量还减小了下载等待的时间。毋庸置疑,尽可能减小程序安装包的大小是十分有必要的。一般来讲,减小程序安装包的大小有两条规律:要么减小程序资源的大小,要么就是减小程序的代码量。这里总结一个简易版的减小安装包大小的Checklist:
确保在build.gradle文件中开启了minifEnabled
与shrinkResources
的属性,这两个属性能够帮助移除那些在程序中使用不到的代码与资源,帮助减小APP的安装包大小。
有选择性的提供对应分辨率的图片资源,系统会自动匹配最合适分辨率的图片并执行拉伸或者压缩的处理。
在符合条件的状况下,使用Vertor Drawable替代传统的PNG/JPEG图片,可以极大的减小图片资源的大小。传统模式下,针对不一样dpi的手机都须要提供一套PNG/JPEG的图片,而若是使用Vector Drawable的话,只须要一个XML文件便可。
尽可能复用已经存在的资源图片,使用代码的方式对已有的资源进行复用,以下图所示:
以上几点虽然看起来都微不足道,可是真正执行以后,可以显著减小安装包的资源图片大小。
开启MinifEnabled,Proguard。打开这些编译属性以后,程序在打包的时候就不会把没有引用到的代码编译进来,以此达到减小安装包大小的目的。
注意由于编译行为额外产生的方法数,例如相似Enum,Protocal Buffer可能致使方法数与类的个数增长。
部分引入到工程中的jar类库可能并非专门针对移动端APP而设计的,他们最开始多是运用在PC或者Server上的。使用这些类库不只仅额外增长了包的大小,还增长了编译时间。单纯依靠Proguard可能没法彻底移除那些使用不到的方法,最佳的方式是使用一些更加轻量化,专门为Android APP设计的jar类库。
设想一下,一个low dpi,API<14的用户手机下载安装的APK里面却包含了大量xxhdpi的资源文件,对于这个用户来讲,这个APK是存在很大的资源浪费的。幸亏Android平台为咱们提供了拆分APK的方法,它可以根据API Level,屏幕大小以及GPU版本的不一样进行拆分,使得对应平台的用户下载到最合适本身手机的安装包。
更多关于安装包拆分的信息,请查看Configure APK Splits与Maintaining Multiple APKs(因为国内应用分发市场的现状,这一条几乎没有办法执行)。
针对不一样的分辨率提供多张精度的图片会额外增长APK的大小,针对这个问题的解决方案是考虑使用VectorDrawable,它仅仅只须要一个文件,可以动态生成对应分辨率的图片。
VectorDrawable经过XML文件描述图片的形状,大小,样式。
经过这种方式,咱们能够显著减小图片资源对安装包大小的影响。
使用VectorDrawable还能够避免由于使用帧动画致使的图片资源过多的状况,以下图所示
前面介绍了VectorDrawable(VD)的优点,可是在使用VectorDrawable的时候,仍是有如下的问题须要特别注意的?
首先VD的加载有异于JPEG/PNG文件,图片文件能够依靠硬件进行纹理的渲染,而VD文件须要先进行加载解析,而后才可以进行纹理的渲染。
其次VD文件适用于简单有规则的图片渲染,不适用于那些纹理过于复杂的图片,这样不只仅会过分增长描述文件的复杂度还可能没法获取到想要的渲染效果。
最后VD文件中关于Path的描述须要尽可能简化,复杂冗余的Path信息不只对获得想要的图片没有益处,还增长了加载渲染的难度。
做者简介:
胡凯,腾讯 Android 工程师,热爱开源与分享,维护 Android 官方培训课程协做项目,关注 Android 应用性能优化的总结与分享,推崇 Android 官方最佳实践。
我的博客:http://hukai.me
Github:https://github.com/kesenhoo。
更多精彩内容欢迎关注bugly的微信公众帐号:
腾讯 Bugly是一款专为移动开发者打造的质量监控工具,帮助开发者快速,便捷的定位线上应用崩溃的状况以及解决方案。智能合并功能帮助开发同窗把天天上报的数千条 Crash 根据根因合并分类,每日日报会列出影响用户数最多的崩溃,精准定位功能帮助开发同窗定位到出问题的代码行,实时上报能够在发布后快速的了解应用的质量状况,适配最新的 iOS, Android 官方操做系统,鹅厂的工程师都在使用,快来加入咱们吧!