性能优化,包括:启动优化,卡顿优化,包体积优化,内存优化,网络优化,耗电优化
性能检测工具
腾讯开源的GT,https://github.com/TencentOpen/GT
(1)什么是GT?
GT(随身调)是一款同时支持安卓手机端和IOS手机端性能测试工具。
即仅凭一部手机,无需连接电脑,就可以对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等)、 开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等等;更重要的是,您可以在任意真实场所、 任何时候做如上的系列事情,这就是“随身调”。如果您觉得GT提供的功能还不够满足您的需要, 您还可以利用GT提供的基础API自行开发有特殊功能的GT插件(仅iOS版支持), 帮助您解决更加复杂的APP调试、测试问题。
启动优化
优化整体思路就是能预加载尽量去预加载,能延迟加载的资源尽量去延迟加载,能异步的业务尽量异步.
1.使用TraceView查看CPU使用情况和各个方法执行时间
2.使用Android SDK自带的deBug
3.使用SyTrace统记方法的耗时时间
1.用户体验优化
(1).主题优化:通过给应用设置一个透明主题,在应用启动完成后再设置本该有的主题,将解决白屏的问题
(2).动画兼容
(3).布局优化
2.异步加载
(1).采用线程加载一些资源,比如第三方SDK初始化,配置信息拉取等相关资源,用线程,线程池,都可以
(2).可以用CountDownLach来实现线程之间相互等待依赖等问题;
总结:启动加载逻辑优化处理,可以采用分步加载、异步加载、延期加载策略来提高应用启动速。
可以在Splash闪屏页的2秒的友好时间内提前进行数据加载和处理基础逻辑,这样进入首页后就能更快的显示页面
卡顿优化
TraceView的使用,查看各个方法的执行时间
影响卡顿的两大因素,分别是界面绘制和数据处理。
界面绘制:主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在 UI 和启动后的初始界面以及跳转到页面的绘制上。
数据处理:导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理 UI 线程,二是数据处理占用 CPU 高,导致主线程拿不到时间片,三是频繁创建对象内存增加导致 GC 频繁,从而引起卡顿。
布局优化
在Android种系统对View进行测量、布局和绘制时,都是通过对View数的遍历来进行操作的。如果一个View数的高度太高就会严重影响测量、布局和绘制的速度。现在版本中Google使用RelativeLayout替代LineraLayout作为默认根布局,目的就是降低LineraLayout嵌套产生布局树的高度,从而提高UI渲染的效率。
• 绘制UI时,尽量减少绘制UI层次,可以用Hierarchy Viewer工具来检测
• 布局复用,使用标签重用layout;
• 提高显示速度,使用延迟View加载;
• 减少层级,使用标签替换父级布局;
• 注意使用wrap_content,会增加measure计算成本;
• 删除控件中无用属性;
• 去除XML 中非必须的背景
绘制优化
降低View.onDraw()的复杂度:
(1).不要在onDraw()中创建新的局部对象;
(2).避免onDraw()执行大量耗时操作
数据处理
不要做复杂数据处理,放到子线程
不要在主线程进行网络访问/大文件的IO操作
总结,一般的卡顿优化:
• 不要在主线程进行网络访问/大文件的IO操作
• 绘制UI时,尽量减少绘制UI层次;减少不必要的view嵌套,可以用Hierarchy Viewer工具来检测
• 当我们的布局是用的FrameLayout的时候,我们可以把它改成merge,可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)
• 提高显示速度,使用ViewStub:当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
• 使用RelativeLayout替代LineraLayout作为默认根布局,降低层次
• 删除控件中无用的属性;
• 布局复用,比如listView 布局复用
• 尽量避免过度绘制(overdraw),比如:背景经常容易造成过度绘制。由于我们布局设置了背景,同时用到的MaterialDesign的主题会默认给一个背景。这时应该把主题添加的背景去掉;
• 去除XML 中非必须的背景
包体积优化
1、资源优化。
Lint 工具删除冗余资源,资源文件最少化等
• res资源优化
(1)只使用一套图片,使用高分辨率的图片。
(2)UI设计在ps安装TinyPNG插件,对图片进行无损压缩。
(3)svg图片:一些图片的描述,牺牲CPU的计算能力的,节省空间。使用的原则:简单的图标。
(4)图片使用WebP(谷歌推出的webp图片格式)的格式(Facebook、腾讯、淘宝在用),体积小,加载快,网络传输快
(5)使用tintcolor(android – Change drawable color programmatically)实现按钮反选效果。
2、使用proGuard 混淆器工具,它包括压缩、优化、混淆等功能。
资源文件混淆
3、图片优化。比如利用 PNG优化工具 对图片做压缩处理。推荐使用 WebP图片格式。
图片只放一套在720p尺寸的
4.减小 so 库
so 库的话,只放一套在arm 平台上的so库
5、插件化热修复开发。比如功能模块放在服务器上,按需下载,可以减少安装包大小
内存优化
1.常见的内存问题:
内存泄露
内存抖动
图片Bitmap相关
2.常见内存泄露原因
1).使用集合类,不用时没有及时把集合类清理及赋空
2).使用Static关键字修饰的成员变量,当前的类无法回收
3).非静态内部类和匿名类(外部类中 持有 非静态内部类的静态对象)
4).资源对象使用后未关闭(对于资源的使用(如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等),若在Activity销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏)
总结,常见内存泄露原因:
• 静态变量导致的内存泄漏
解决办法:将内部类设为静态内部类或独立出来;使用context.getApplicationContext()。
• 单例模式导致的内存泄漏
解决办法:传参context.getApplicationContext()。
• 属性动画导致的内存泄漏
解决办法:在Activity.onDestroy()中调用Animator.cancel()停止动画。
• Handler导致的内存泄漏
解决办法:
1.使用静态内部类+WeakReference弱引用,静态内部类Handler持有Activity的弱引用;
2.当外部类结束生命周期时清空消息队列;
• 线程导致的内存泄漏
解决办法:将AsyncTask和Runnable设为静态内部类或独立出来;在线程内部采用弱引用保存Context引用。
• 资源未关闭导致的内存泄漏
解决办法:在Activity销毁的时候要及时关闭或者注销。例如:
① BraodcastReceiver:调用unregisterReceiver()注销;
②Cursor,Stream、File:调用close()关闭;
③Bitmap:调用recycle()释放内存(2.3版本后无需手动)。
• Adapter导致的内存泄漏
详情:不使用缓存而只依靠getView() 每次重新实例化Item,会给gc制造压力。
解决办法:在构造Adapter时使用缓存的convertView。
• WebView导致的内存泄漏。
详情:WebView比较特殊,即使是调用了它的destroy方法,依然会导致内存泄漏。
解决办法:其实避免WebView导致内存泄漏的最好方法就是让WebView所在的Activity处于另一个进程中,当这个Activity结束时杀死当前WebView所处的进程即可,我记得阿里钉钉的WebView就是另外开启的一个进程,应该也是采用这种方法避免内存泄漏。
• 集合类泄漏
详情:比如全局map等有静态应用,最后没有做删除。
解决办法:在onDestry时回收不需要的集合。
网络优化
常见的网络优化方案如下:
• 尽量减少网络请求,能够合并的就尽量合并
• 避免DNS解析,根据域名查询可能会耗费上百毫秒的时间,也可能存在DNS劫持的风险。可以根据业务需求采用增加动态更新IP的方式,或者在IP方式访问失败时切换到域名访问方式。
• 大量数据的加载采用分页的方式
• 网络数据传输采用GZIP压缩
• 加入网络数据的缓存,避免频繁请求网络
• 上传图片时,在必要的时候压缩图片
耗电优化
耗电的原因其实很多,这里我就讲一下几种优化方案,几种优化方案如下:
• 合理的使用wake_lock锁,wake_lock锁主要是相对系统的休眠(这里就是为了省电,才做休)而言的,意思就是我的程序给CPU加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。有的情况如果不这么做就会出现一些问题,比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。所以微信里面是有大量使用到了wake_lock锁。
• 使用jobScheduler2,集中处理一些网络请求,有些不用很及时的处理可以放在充电的时候处理,比如,图片的处理,APP下载更新等等;
• 计算优化,避开浮点运算等。
• 数据在网络上传输时,尽量压缩数据后再传输,建议用FlatBuffer序列化技术,这个比json效率高很多倍,不了解FlatBuffer,建议找资料学习一下。
ANR
一个进程发生了ANR后,系统会在 /data/anr目录下创建一个文件 traces.txt,通过分析该文件可定位出ANR的原因