眼看 Android 9.0 都出了,你还对安卓开发一窍不通?
别急,让小编教你如何用正确的姿势和安卓系统生宝(ying)宝(yong)。选择成为安卓开发,首先要理解移动计算环境,那这些东西为何重要?
理解安卓的运行环境才能真正掌握我们所讲的开发工作的“最佳实践”。开发者要时刻牢记移动设备不同于台式机和服务器,你所能使用的计算资源非常受限。不将其纳入考量范围而直接上手开发不止会让应用表现欠佳,还会在消耗大量内存的同时拖慢系统运行速度。若干问题累积起来会严重干扰设备运行,造成糟糕的用户体验。
我们在这里对移动设备开发上,会面临的限制条件进行了梳理和总结:
内存
移动设备内存偏小,虽然并不是所有设备都存在这个问题,但它影响着当前生态系统中的大多数机器。要知道,开发者所拥有的机型往往运行速度更快、计算能力更强,但这不代表着所有目标设备都是如此。
三年前当开发者开始使用1GB到2GB 内存的Nexus5 时,512MB内存才是大多数设备的标配。以最新款设备来估算你的应用所处的运行环境并不合适。另外很重要的一点是安卓系统是多任务多服务并行执行的,同一时间可能有很多 activity 在跑。系统这一特征对于创造良好的用户体验很重要,使用者可以在无需重新加载的情况下在近期使用的应用间自由切换。
不过,相应代价就是当有应用消耗了过多的内存时,剩余应用可使用的资源就非常有限。系统会终止其运行并回收计算资源以减缓内存开销,这样在用户重新切换到该应用时必须重新加载。
总之,请尽可能降低你所编写应用的内存消耗,否则整个系统都会受其影响。
CPU
首先纳入考量范围的还是用户实际使用设备的状态,虽然你很清楚手上设备的 CPU比起台式机甚至服务器计算能力要弱很多,但用户所持设备上的CPU可能还要受限一些。低端设备市场广阔且销量很大,不要只以你手上的最新设备作为应用测试基准。在大多数时间,CPU 都不是满负荷运行的。系统会尽己所能降低CPU功耗以保持电量防止设备过热,在屏幕关闭、没有用户输入、动画渲染停止这些情况下系统会悄悄地进行这项工作。
针对这一系统特性,在应用开发时有这两点要注意: (1) 你通常情况下不能使用一个满负荷运转的 CPU。 (2) 在调用诸如动画绘制这种功能时,系统会“壕气地”运转,避免降低功耗可能带来的卡顿问题。所以除非在必要情况下,不要以牺牲电量为代价追求绝对性能。
GPU
关于GPU 的内容和刚刚讲的 CPU 部分相似。另外还有几点补充:
· 传输代价: 将一个大的纹理/位图载入GPU代价高昂,你载入的文件越大,花费时间越长。频繁地进行图像相关操作,改变位图、增改大量文字内容 (特别是字体库庞大的语种) 会造成运行过载,因为有太多纹理要上传到 GPU 进行渲染。
· 相比于以基本图元渲染衡量的GPU性能指标,实际渲染像素数目才是和GPU 表现直接相关的。硬件可能无法在一帧内完成高分屏所有像素的绘制。该问题被称为过度绘制(overdraw),在重叠区域进行频繁绘图,比如在屏幕上依次绘制桌面背景、容器背景、半透明视图就可能引发这种问题。
内存 == 性能
我们着眼于内存优化,它与系统运行表现息息相关。内存的分配、管理、回收都需要消耗计算资源,内存使用量直接反映了应用对设备的影响。单个应用占用过多内存对其它应用和整个系统来说都不是好事,还会消耗过多电量。
使用低端设备
摩尔定律不只预示着你会拥有更快更强大的机器,也说明一台还不错的机器能以更便宜的价格获取到。低端机型的销量很大,使用你能找到的最老旧的设备测试应用对开发是一种保障。
流畅渲染
理想的无跳帧状态要求每帧16 毫秒左右的渲染时间。处理输入、调整布局等等下一帧绘制的准备工作都要在这段时间完成。这样才能为动画和触控操作提供支持,达到 60 fps 的流畅效果。16 毫秒是一个上界,如果应用渲染速度逼近这个上界,5 毫秒左右的垃圾回收任务的插入都会对绘制造成明显影响。缓冲区恒定以六十分之一秒的时间间隔读入数据,17 毫秒的绘制完成速度也会将帧率降到 30 fps 的水平。
运行时环境
在 Lollipop 版本之前,安卓底层使用 Dalvik 虚拟机。 ART虽然在KitKat 版本里也作为测试版的可选项出现过,只有在 Lollipop 才正式采用。
Dalvik 是一个即时编译器,能够做部分运行时优化。ART 具有提前编译能力,做起优化来更狂野。当然这两种编译选项在优化任务上都还有待改进的地方。总体上ART 相比 Dalvik 有 30–200% 的性能提升。
垃圾回收
垃圾回收机制(Garbage Collection -GC) 特指运行环境对不再被引用的对象的内存释放过程。有太多资源待处理的话它也会对渲染帧率造成明显影响。
Dalvik 和 ART在垃圾回收的实现方式上很不相同。Dalvik里对象一旦分配就会固定到堆中的特定位置,运行时间久了碎片化严重,虚拟机难以找到合适的地方新建对象,垃圾回收很容易耗费掉大约10–20毫秒的时间,具体消耗与应用新建对象数目相关。
ART 会在设备空闲期间对堆进行整理,同时它给位图等大文件准备了单独的堆,使得垃圾回收执行速度大大提升,通常保持在 2–3 毫秒间。
2–3 毫秒在一些时候也会造成跳帧等情况,所以还是要注意合理分配和使用内存空间提高渲染速度。
UI 线程
很多运行问题都与负责界面的专门线程相关。安卓采用单线程界面系统,任务串行执行,任何干扰绘图的情况都会影响到绘制帧率。
在 Lollipop 版本里,渲染线程出现并被用于向 GPU 发送绘图命令。这降低了UI 线程的工作负荷,但是输入、滚动还有动画都在 UI 线程中运行,所以该线程必须要保持快速响应能力。
存储
不同设备的存储能力有很大差异,一些机器可能存放 500 MB 文件就要卸载部分应用来腾出空间。初看起来移动设备的闪存应该像笔记本的SSD 那样可以快成一匹马,实际情况可不是这样。还有使用 SD 卡做存储扩展时,实际传输速度依厂商、芯片、SD 卡的不同会有很大差异,开发者也需要将这种情况考虑在内。
网络
并不是所有 wifi 都有五星好评,4G时代还有很多地区主要覆盖的是 2G 网络,针对网络环境有以下两点要注意:
· 对于依赖高速网络的应用,最好设置网络状态检测机制,只有当条件满足时才进行多媒体资源下载等活动。
· 避免过多进行同步操作,你希望保持信息的绝对实时性并不代表着用户愿意这样做,严重消耗网络资源且损耗电池寿命的频繁同步操作请尽可能地避免。
系统村
每个人都认为自己开发出来的应用宝宝是棒棒哒。不过一个设备就像一个小部落,系统除了运行你的应用之外,还要负责自身运转以及管理诸多应用。占用过多资源的应用会对其它“村民”带来困扰,在必要情况下它会被强制终止以释放资源。一旦用户需要切换回该应用,就得重新加载才行;这会让大家认为它不够可爱。
所以做个系统村的好公民很重要,贪婪的程序是要被剔除的。
共享区域的悲剧
应用通常不会因为自身运行而造成坏的用户体验。但在实际设备当中,资源被多个应用共享,很难保证不出现僧多粥少的情况。
就拿一个频繁同步数据的应用作例子,一个应用还不算什么。当系统运行着超过 100个同类应用的时候,轮轴转的系统下即使你的流量撑得住电量也会很快耗尽。相比之下一个操作次数少、批量更新的应用比它们不知高到哪里去。很多时候,开发者需要将应用放到安卓系统的“公地”里去考量。
最后,小编还为大家准备了一波小福利:
福利一:Android各大面试专题整理+详解
需要这些进阶视频和面试专题文档,可以加Android进阶交流群,找群管理免费获取;100595838点击链接加入群聊
福利二:Android高级进阶系统视频课程
这是一套针对有工作经验基础的Android开发者设计的系统进阶教程。详细而且深入的覆盖了上面技术大纲里的所有技术点。
如果对Android开发感兴趣,欢迎大家关注我们,和资深工程师一起进行学习与交流。
—————END—————