Google Developing for Android 一 - 相关上下文介绍

前几天在G+上看到Google Developers站点,有一个Android系列的文章,分享到个人微博,周末闲来没事就学写了下,把它们简单的翻译了下,没想到一发不可收拾,六篇文章全部都翻译完了,有些地方省略了部分示例的描述或者换了另一种表述,如果有理解的不准确的地方,还望指正



原文:Developing for Android, I:Understanding the Mobile Context

context或者这些建议为何如此重要

对于理解这些最佳实践的相关上下文是非常重要的。特别是明白移动端存在一些严重的限制,和台式机以及服务器端的计算是完全不同的。因此,在开发应用的时候,如果没有将这些限制考虑进去,将会导致很大的性能问题和内存消耗,这不是针对于某一个应用而言,而是针对整个设备,因为很多拥有相同性能问题的app共同导致了一个性能很差的设备。
以下使一些重要的约束,限制和现实,在过去以及将来的移动设备中都很重要。

移动设备的内存是很有限的。当然不是指所有的设备,不过对于大多数的移动系统是这样的。对于开发者来说,我们使用的手机可能是比大多数用户现在或者将来所使用的设备更快更好,也更新。比如,拥有一个带有 1GB-2GB内存Nexus 5对于我们来说是比较合理的,512M的内存配置的手机在美国以及一些新兴的低端市场是很常见的。因此,以2GB或者更大内存的标准去衡量一个App是不现实的。
明白Android会运行多个Activity和多个并行的Service也是很重要的。在最近App列表中切换而不是重新启动一个App的方式对于创造出一种很好的体验是非常重要的。但是这样意味着如果这些app消耗了比它们本应该消耗的更多内存,那么留给其它的应用的系统内存就很少了。如果这种低内存情况发生,应用就不能保留在后台,系统会干掉app的进程,用户就被迫以重新启动的方式去开启一个App,显然这样的体验就比较差。

即使最高级别的移动设备的CPU也要远远比台式设备的CPU慢。当然即使你意识到了这一点,你也应该考虑那些大多数使用了比你更慢的CPU的用户。适用于内存的建议也同样适用于CPU:世界范围的低端设备一直在售卖,因此不要以你自己相对较好的设备的性能为基准,因为跑在那些大多数拥有较慢处理器和更低内存配置的设备上的差别是非常大的。
另一个问题是,CPU的处理器是不会一直保持在最大的速度的。当系统认为电池的发热程度达到了临界点的时候,就会导致CPU降频。一般来说,这些情况发生的时候用户可能不会注意到,比如屏幕关闭了,或者输入事件不响应了,或者动画不再运行了。降频对App来说有两层含意:(1)你的app可能在很多情况下降低运转速度,因此,即使是一个不错的CPU,你也只能够获取一个有限的速度 (2)你的app可能做了一些操作导致CPU无法降频,使得CPU始终维持在处理速度最大化的状态(比如,频繁,长时间或者无休止的动画应该被避免,因为在动画期间,为了让动画更加流畅,系统将试图以最大的功率来运行)。显然,你不想去权衡较高的CPU速率和使用对降低电池的使用寿命的影响,因此当你不需要的时候,尽量避免它们。

GPU性能的建议类似于CPU,当然还有些额外需要注意的地方:

  • 上传是消耗资源的
    在任何系统上上传大大纹理(bitmap)都是比较消耗资源的,bitmap越大,操作时间越长。因此,这意味着频繁大进行bitmap相关大图形化操作会导致性能问题,比如bitmap,paths(会被光栅化到Bitmap中),和大量到新的或者不同的text(有种问题是大量的非英文的字符集合的导致的问题)
  • 我们通常面临的问题并不是几何的绘制,甚至一些纹理的绘制,而是大量的像素填充到高分辨率的设备上。这些高分辨率的屏幕会导致一个性能问题,因为在动画某一帧中硬件不能够填充如此多的像素。比较常见的是过渡绘制,由于重叠的内容,比如window背景,内容背景和一些半透明的View,就会导致应用会多次重绘同一块区域。

内存 == 性能

在这个系列中,很多的指导会围绕着内存的使用来讨论。但有一点很重要,就是内存是和运行期间的性能以及电池的寿命是紧紧关联的。因为你分配的内存越多,设备就要为你的应用做更多的工作。内存分配和回收增加了运行期间的活动会。大的heap内存意味着你的你的app占用了更多的内存,但是设备总体的内存是减少了,会导致其它的活动被迫减少自己的内存开销,或者直接被kill掉,这样将导致设备的总体性能,因为用户会在不同的活动中切换,而这些Activity需要重新启动。更的的Heaps也会导致更长时间的GC中断,因为一个较大的heap内存会导致内存的分配和回收消耗更长的时间。这些所有的行为都会消耗更多的电量,因为设备所做的工作越多,电池就会消耗越多也更有限。

因此这个系列的文章很多涉及到了性能问题,事实就是这些技术对于写出一个好的App来讲,是非常重要的。

因此这篇文档的最佳实践所涉及到的点不是内存就是性能,这些技术也是能够写出一个好的app所必须的。

上面很多部分也提到,就是开发者所使用的设备可能比大多数未来使用者的设备都要好。虽然在2015年2GB已经是主流,但是很多在世界范围的很多新兴市场仍然卖着512M的设备。

更平滑的帧率

对于Android的最佳体验是低于16毫秒的帧率。也就是说应用必须在16毫秒内完成所有的输入,布局,绘制和其它所有的事情。这个速度允许系统在动画和输入事件的过程中以60帧美妙的速度渲染。动画必须能在60帧率的时间内完成必要部分的重绘已完成平滑的动效。问题更多的是,很多应用通常可以在16ms内完成渲染,但它丢弃了当前帧,并且之后不能够延续之前的帧率,这种不连续的间隔会容易会引起用户的注意。

平滑的完成一帧意味着任何特殊的帧需要执行所有的渲染代码(包括framework发送给GPU和CPU绘制到缓冲区的命令)都要在16ms内完成。这也就是为什么即使在垃圾回收事件中丢失了5ms也会有很大的影响。因为它严重限制了一帧时间内剩余的绘制时间。越接近16ms,在垃圾回收事件触发的时候,就越容易导致卡顿。

缓冲区只能够在

有两个运行环境需要主要:Dalvik和ART。在5.0版本之前,Android使用Dalvik。开发者可以在4.4版本中选择ART进行测试。但是它只会在5.0的系统中运行。

Dalvik是采用的时 JIT编译器,能够执行一些细微的优化,但是和其它的很多JIT编译器是不同的。ART是一个Ahead-of-Time 编译器,比Dalvik会做更多的优化。然而,不论是Dalvik还是ART提供的优化水平与服务器和台式机运行平台都是不一样的。比如方法的内联和escape analysis。有一些内联,ART会在叶子方法上执行,但是更进一步的优化只可能在将来的版本中出现,因为未来会有新的优化编译器。由于app开发者可能需要支持老得版本,他们需要继续关心现在和之前编译器的限制。

通常,ART性能要比Dalvik提升30 - 200+%。ART的编译器会执行更多的优化,比如,实质性的提升接口的分发。ART优化的范围要更大些,内存分配也更快。最终,应用的线程会更少的受限于垃圾回收,短时间的中断次数也会减少。

垃圾回收器

垃圾回收器是一个通过运行期间释放那些不再引用的内存的过程。GC也是导致严重性能问题的原因之一,如果GC所做的工作超过了那些必须的工作,那么留给应用平滑的帧率的时间就越少。

在Dalvik和ART中的垃圾回收器实质上是不同的。一个主要的区别就是Dalvik不是一个移动的回收器。就是说所有的分配对象都将呆在Heap的同一个地方,这对于Dalvik来说,为新的对象找到可分配的内存就会更加困难和耗时,特别是当Heap颗粒化和碎片化并且又有大量对象急需内存的时候。Heap碎片化也会导致GC更频繁的中断,因为Dalvik会尝试清理从那些无用的heap。这些GC中断是非常消耗资源的,并且在正常的情况下一个比较快的手机也会很容易耗费掉10-20ms的时间。很重要的是,垃圾回收的时间与在堆中对象的数量成正比,这是尽可能避免分配对象的另一个原因。

ART会动态的提升垃圾回收的效率。比如,ART是一个移动的垃圾回收器,在应用长时间单中止时,它会让heap变得紧凑而不会影响用户的体验。而且,这里有一些独立的专门用于大对象的heap,比如像bitmap这样的对象,ART就会更快的找到内存,而不是有序的遍历碎片化的heap。在ART中的中断,通常在2-3ms间。

尽管ART相对于Dalvik来说的垃圾回收来说有一个很大的性能提升。但是在写Android app的时候,仍然需要注意的是即使是2-3ms的时间对于超过16ms帧率的界限也是足够的。因此,尽管垃圾回收在5.0之后不再是耗资源的行为,但也是始终需要尽可能避免的,特别是在执行动画的情况下,可能会导致一些让用户明显感觉的丢帧。

UI Thread

很多的性能和卡顿问题是由于我们在UI线程中做了大量的工作。Android是一个独立线程的UI系统,在这里所有发生在View上的操作,包括View的绘制,都发生在Activity的UI线程上。任何发生在相同UI线程的操作,即使是View的绘制也可能导致卡顿,因为它没有时间在16ms的时间内达到一个平滑的帧率。

在5.0版本里,framework引入了“Render Thread”,用于向GPU发送实际渲染的操作。这个线程减轻了一些UI Thread减少的操作。但是输入,滚动和动画仍然在UI thread,因为thread必须能够响应操作。

存储的指标在不同的Android设备上是不同的,但是可能是比较慢而且是受限制的。移动设备只有8G(2015年,在低于中等水平的设备中很常见)甚至4G搭配一个SDcard,去存储整个系统,所有的应用以及所有的音频,很容易就满了。在这种情况下,一个app可能导致用户为它删除其它内容以便获取更多空间,或者因为每有足够的空间就直接卸载它。

存储性能也是需要关心的点。移动设备和桌面设备的硬盘相比是完全不同的。

同时,也要注意到外部存储SDcard的内存在I/O性能上可能有很大的不确定性,其依赖于供应商,芯片和速度指标。但是App不应该阻止用户使用SDcard,因为很多设备确实内存比较小,需要它作为扩展。

位于在城市中的大多数软件开发者来说拥有一些现代的基础设施和移动网络是很简单的。但很多其它地区并不具备这样的设施。更别说LTE或4G了。很多国家的地区还是2G的网络而且可能还要承受大量数据的传输。这样就会导致两个通用的问题:

  • 依赖于快速的网络速度
    App严重依赖大媒体数据(Video,audio,images)在网络基础较差的地方可能没有选择。但是避免下载,直到条件允许的情况下再去下载也是App体验的一部分
  • 多度同步
    也许你的App希望更新一些信息,但是用户并不需要它,更重要的问题,设备并不应该承受所有应用程序与网络不断交互的情况。这种动态会很容易地使设备持续工作而不能够进行休眠,最终影响电池的续航。

每一个设备都是一个村落

用户的设备上会安装很多的应用,包括系统的UI和Launcher App。如果你的App使用了越多的资源(内存,CPU,GPU,电池),那么其它应用就会越少,那么呈现给的用户的设备就会越差。如果你的处理越多,当系统需要更多内存的时候,就越有可能试图从内存中干掉它,那就意味着你的App就要花费更长时间去开启,从而导致一种很不好的体验。

因此,在Android设备上成为一个良好的公民吧。也是每个App应该去做的,因为如果每个应用都贪婪,那么最终痛苦是设备和用户。

平民的灾难

移动设备最大的问题是一些app在自己感兴趣的情况下活动导致了设备的整体性能和体验。分析特定app可能不是应用需要修复的标志性的问题。但是对设备整体的影响,所有的app都遭受资源的限制,最终用户的体验很差。

一个好的例子是观察某个应用是否太频繁的同步。那意味着特定的应用在以特定的频率访问服务器。但是如果用户有超过100个应用都在这样做,相比较那些延迟,批处理的同步系统来说,结果就是设备将永远不能够休眠并且很快耗完电。

时间: 2024-10-21 13:47:03

Google Developing for Android 一 - 相关上下文介绍的相关文章

Google Developing for Android 二 - Memory 最佳实践 // lightSky‘Blog

Google Developing for Android 二 - Memory 最佳实践 |   分类于 Android最佳实践 原文:Developing for Android, II The Rules: Memory 在决定应用的行为,是否有好的用户体验以及整体的设备体验来说,内存的使用可能是独立因素中最重要的.内存因素包括应用的内存占用,以及内存搅动(导致的垃圾回收会对运行期间的性能有影响). 避免在循环中分配内存 内存分配虽然不可避免,但是应尽可能的避免,特别是在平凡的调用的代码块

【ALearning】第二章 Android工程相关知识介绍

本章主要初步介绍Android工程开发环境的搭建,以对Android项目整体的认识与了解.本章包括Android开发环境搭建.第一个Android项目Hello World与Android项目的文件目录结构介绍. Android开发环境搭建 Android开发环境的搭建方式有两种,分别是Eclipse/MyEclipse+ADT+Android SDK和Android Developer Tools.前者方式的开发环境搭建,参看[http://blog.sina.com.cn/s/blog_4e

Google Developing for Android 学习总结

避免在循环中使用内存 也可理解为在循环中尽可能少创建对象,自定义控件避免在ondraw里面频繁创建paint对象. 尽可能避免内存分配 对象缓存: 常量通过类级别或者静态来进行缓存. 对象池: 同一种类型的多种对象,考虑使用对象池而不是分配频繁的分配内存. (不是很理解,还需深入学习) 使用ArrayList. android集合类: 使用ArrayMap或者simpleArrayMap代替HashMap. 需要修改的方法: 尽可能少用对象类型而是用原始类型的数据,android提供的Spars

【ALearning】第五章 Android相关组件介绍(一)Activity

Android应用程序由一些零散的有联系的组件组成,通过一个工程manifest绑定在一起.在manifest中,描述了每一个组件以及组件的作用,其中有6个组件,它们是Android应用程序的基石. Activities(活动) Service(服务) Content Provider(内容提供者) Intent(意图) Broadcast Receiver(广播接收器) Notification(通知) 在这里我们提到了组件(Component)的概念,组件(Component)是对数据和方法

Android UI相关开源项目库汇总

最近做了一个Android UI相关开源项目库汇总,里面集合了OpenDigg 上的优质的Android开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star. 抽屉菜单 MaterialDrawer ★7337 - 安卓抽屉效果实现方案 Side-Menu.Android ★3865 - 创意边侧菜单 FlowingDrawer ★1744 - 向右滑动流动抽屉效果 SlidingRootNav ★1338 - 仿DrawerLayout的View

Android 6.0 Marshmallow介绍

Android 6.0 Marshmallow介绍 Android 6.0 (M) 为用户和应用开发者提供了新功能.本文旨在介绍其中最值得关注的 API和重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 1.Android 6.0新增功能与特性 指纹身份验证: 此版本提供了一些新的 API,在受支持的设备上,用户只需扫描其指纹即可完成身份验证,这些 API 还可与 Android 密钥库系统结合使用. 要通过指纹扫描验证用户身份,请获取新 FingerprintManager 类的实例,

Android Studio重构之路,我们重新来了解一下Google官方的Android开发工具

Android Studio重构之路,我们重新来了解一下Google官方的Android开发工具 记得我的第一篇博客就是写Android Studio,但是现在看来还是有些粗糙了,所有重构了一下思路,覆写了一篇 Google主推-Android开发利器--Android Studio,这可能是最全的AS教程! Android Studio,自Google2013年发布以来,就倍受Android开发者的喜爱,我们本书,就是基于Android Studio来进行案例演示的,大家都知道,Android

Android的SQLite使用介绍

Android的SQLite使用介绍 一.SQLite的简介 Android当中内置SQLite数据库,那个SQLite有什么特点呢? SQLite 是一个开源的嵌入式关系数据库,实现自包容.零配置.支持事务的SQL数据库引擎. 其特点是高度便携.使用方便.结构紧凑.高效.可靠. 与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下 - 只要确保SQLite的二进制文件存在即可开始创建.连接和使用数据库.在于个人使用SQLite的体验中,SQLite最大的优点就是高度便携

【转】Android 4.2蓝牙介绍

原文网址:http://blog.csdn.net/innost/article/details/9187199 Tieto公司某蓝牙大牛写得<程序员>投稿文章 Android 4.2蓝牙介绍 蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand.Blatand的英文之意就是Blue tooth.这是因为这位让丹麦人引以为傲的国王酷爱吃蓝莓以至于牙龈都被染成蓝色.由于Blatand统一了丹麦和挪威,所以,作为无线通信技术的一种,蓝牙技术之所以取名Bluetooth可谓