比较Android与iOS的硬件设备,android的硬件配置往往都强于iOS,出现性能差异最主要的原因还是在软件上,android系统的碎片化和兼容性就是罪魁祸首
各大厂商对Android原生系统进行定制,导致开发者的适配工作越来越难,作为开发者我们能做的是什么呢,下面就是作为开发者我们可以提升性能,优化体验的几点:
- 快 – 使用时避免出现卡顿,响应速度快,减少用户等待的时间,满足用户期望。
- 稳 – 减低 crash 率和 ANR 率,不要在用户使用过程中崩溃和无响应。
- 省 – 节省流量和耗电,减少用户使用成本,避免使用时导致手机发烫
- 小 – 安装包小可以减少用户安装成本
逐点分析:
应用启动慢,经常卡顿可以分为四个场景:UI绘制渲染、应用的启动、页面的跳转、事件的响应。这四种情况可以统称为两大类:
界面绘制 主要原因是因为绘制的层级深、页面复杂、刷新不合理。
数据处理 数据量处理太大,可以分为三种情况,一是数据在处理UI线程,而是数据占用的CPU高,导致主线程拿不出时间片,三是内存增加导致GC频繁
影响绘制的根本原因有以下两个方面:
- 绘制任务太重,绘制一帧内容耗时太长
- 主线程太忙,根据系统传递过来的VSYNC信号来时还没准备好数据
主线程主线程关键职责是处理用户交互,在屏幕上绘制像素,并进行加载显示相关的数据,所以特别需要避免任何主线程的事情,这样应用程序才能保持对用户操作的即时响应。总结起来,主线程主要做以下几个方面工作:
- UI 生命周期控制
- 系统事件处理
- 消息处理
- 界面布局
- 界面绘制
- 界面刷新
除此之外,特别复杂的数据计算和网络请求尽量避免放在主线程
界面绘制过度的问题可以依靠一些工具
优化建议
1,布局优化
布局是否合理主要影响的是页面测量时间的多少,我们知道一个页面的显示测量和绘制过程都是通过递归来完成的,多叉树遍历的时间与树的高度h有关,其时间复杂度 O(h),如果层级太深,每增加一层则会增加更多的页面显示时间,所以布局的合理性就显得很重要。
那布局优化有哪些方法呢,主要通过减少层级、减少测量和绘制时间、提高复用性三个方面入手。
总结如下:
- 减少层级。合理使用 RelativeLayout 和 LinerLayout,合理使用Merge。
- 提高显示速度。使用 ViewStub,它是一个看不见的、不占布局位置、占用资源非常小的视图对象。
- 布局复用。可以通过 标签来提高复用。
- 尽可能少用wrap_content。wrap_content 会增加布局 measure 时计算成本,在已知宽高为固定值时,不用wrap_content 。
- 删除控件中无用的属性。
2,避免过度绘制
过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。
如何避免过度绘制呢,如下:
- 布局上的优化。移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片
- 自定义View优化。使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。
3,启动优化
通过对启动速度的监控,发现影响启动速度的问题所在,优化启动逻辑,提高应用的启动速度。启动主要完成三件事:UI 布局、绘制和数据准备。因此启动速度优化就是需要优化这三个过程:
- UI 布局。应用一般都有闪屏页,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。
- 启动加载逻辑优化。可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。
- 数据准备。数据初始化分析,加载数据可以考虑用线程初始化等策略。
4,合理的刷新机制
在应用开发过程中,因为数据的变化,需要刷新页面来展示新的数据,但频繁刷新会增加资源开销,并且可能导致卡顿发生,因此,需要一个合理的刷新机制来提高整体的 UI 流畅度。合理的刷新需要注意以下几点:
- 尽量减少刷新次数。
- 尽量避免后台有高的 CPU 线程运行。
- 缩小刷新区域。
5,其他
在实现动画效果时,需要根据不同场景选择合适的动画框架来实现。有些情况下,可以用硬件加速方式来提供流畅度。
借助一些内存分析工具
常见内存泄漏场景
- 资源性对象未关闭。比如Cursor、File文件等,往往都用了一些缓冲,在不使用时,应该及时关闭它们。
- 注册对象未注销。比如事件注册后未注销,会导致观察者列表中维持着对象的引用。
- 类的静态变量持有大数据对象。
- 非静态内部类的静态实例。
- andler临时性内存泄漏。如果Handler是非静态的,容易导致 Activity 或 Service 不会被回收。
- 容器中的对象没清理造成的内存泄漏。
- WebView。WebView 存在着内存泄漏的问题,在应用中只要使用一次 WebView,内存就不会被释放掉。
优化建议
没有内存泄漏,并不意味着内存就不需要优化,在移动设备上,由于物理设备的存储空间有限,Android 系统对每个应用进程也都分配了有限的堆内存,因此使用最小内存对象或者资源可以减小内存开销,同时让GC 能更高效地回收不再需要使用的对象,让应用堆内存保持充足的可用内存,使应用更稳定高效地运行。常见做法如下:
- 对象引用。强引用、软引用、弱引用、虚引用四种引用类型,根据业务需求合理使用不同,选择不同的引用类型。
- 减少不必要的内存开销。注意自动装箱,增加内存复用,比如有效利用系统自带的资源、视图复用、对象池、Bitmap对象的复用。
- 使用最优的数据类型。比如针对数据类容器结构,可以使用ArrayMap数据结构,避免使用枚举类型,使用缓存Lrucache等等。
- 图片内存优化。可以设置位图规格,根据采样因子做压缩,用一些图片缓存方式对图片进行管理等等。
省电,在 Android5.0 以前,在应用中测试电量消耗比较麻烦,也不准确,5.0 之后专门引入了一个获取设备上电量消耗信息的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系统电量分析工具,和Systrace 一样,是一款图形化数据分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况,最后提供一些可供参考电量优化的方法。
除此之外,还有一些常用方案可提供:
- 计算优化,避开浮点运算等。
- 避免 WaleLock 使用不当。
- 使用 Job Scheduler。
减少安装包大小的常用方案
- 代码混淆。使用proGuard 代码混淆器工具,它包括压缩、优化、混淆等功能。
- 资源优化。比如使用 Android Lint 删除冗余资源,资源文件最少化等。
- 图片优化。比如利用 AAPT 工具对 PNG 格式的图片做压缩处理,降低图片色彩位数等。
- 避免重复功能的库,使用 WebP图片格式等。
- 插件化。比如功能模块放在服务器上,按需下载,可以减少安装包大小。