《Android应用性能优化》1——代码

来源:互联网 发布:商桥2016软件下载 编辑:程序博客网 时间:2024/06/06 05:12
1、Java代码优化

1.1 代码执行

  通常情况下,不必看应用的字节码。在平台是Android2.2(Froyo)和更高版本的情况下尤其如此,因在Android2.2中引入了实时(JIT)的编译器。Dalvik JIT编译器把Dalvik字节码编译成本地代码,这可明显加快执行速度。JIT编译器(JIT)可显著提高性能,因为:

  1. 本地代码直接由CPU执行,而不必由解释执行;
  2. 本地代码可为特定架构予以优化

  谷歌基准测试显示,Android2.2的代码执行速度比Android2.1块2到5倍。虽说代码的具体功能会对结果产生很大影响,但可肯定的是,使用Android2.2及更高版本会显著提升速度。

  对于无JIT的Android2.1或更早的版本而言,优化策略的选用可能会因此受到很大影响。若打算针对运行Android1.5(Cupcake)、1.6(Donut),或2.1(eclair)的设备开发,你要先仔细地审查应用在这些环境下需提供哪些功能。此外,这些运用Android早起版本的旧设备是没新设备强劲的。尽管运行Android2.1和更早版本的设备所占的市场份额正在萎缩,但直到2011年12月,其数量仍占有约12%。可选策略有3条:

  1. 不予优化:不予优化,因为应用在这些旧设备上运行得相当缓慢;
  2. 限制最低API:限制应用中Android API等级为最低8级,让它只能安装在Android2.2或更高版本上;
  3. 禁掉高耗功能:即使没有JIT编译器,也要针对旧设备优化,给用户以舒畅的体验。也就是说禁掉那些非常耗CPU资源的功能

 1.3 缓存结果

使用SparseArray充当缓存

  定义一个缓存时,使用HashMap,可胜任这项工作。不顾,Android定义了SparseArray类,当键是整数时,它比HashMap效率更高。因为HashMap使用的是java.lang.Integer对象,而SparseArray使用的是基本类型int。因此使用HashMap会创建很多Integer对象,而使用SparseArray则可避免这种情况。

注意:Android定义了多种类型的稀疏数组(sparse array):SparseArray(键为整数,值为对象)、SparseBooleanArray(键为整数,值为boolean)和SparseIntArray(键为整数,值为整数)

LRU和MRU策略

  所谓的LRU(Least recently used)算法的基本概念是当内存的剩余的可用空间不够时缓冲区尽可能的先保留使用者最常使用的数据换句话说就是优先清除较不常使用的数据”,并释放其空间之所以较不常使用的数据要用引号是因为这里判断所谓的较不常使用的标准是人为的、不严格的所谓的MRU(Most recently used)算法的意义正好和LRU算法相反,Android现在没有类似MruCache类,考虑到MRU缓存不常用,这并不奇怪

1.4 API等级

版本的分化主要体现在:屏幕分辨率、实体物理键盘、硬件图形加速器及处理器上

1.6 响应能力

  主线程主要处理的事情:

  1. 按键事件接收;(例如,View.onKeyDown()和Activity.onKeyLongPress());
  2. 绘制View(View.onDraw());
  3. 产生生命周期事件(例如,Activity.onCreate());

  Activity的onCreate()方法一般会包含调用setContentView或任何其他负责展开资源的方法。因为展开资源是一个开销相对较大的操作,所以你可通过降低布局(Layout,XML文件定义应用的外观)复杂性来使资源展开加快。几个降低布局复杂性的步骤如下:

  1. 使用RelativeLayout代替嵌套LinearLayouts,尽可能保持“扁平化”的布局。另外,减少创建的对象数量,也会使事件的处理速度加快
  2. 使用ViewStub推迟对象创建

  注意:因为可能有很多项目在列表中,所以要特别注意ListView布局。你可使用SDK的layoutopt工具来分析布局

  优化的基本原则是保持应用的持续响应,让主线程尽可能快地完成任务。这句话也常用另一个说法,在主线程当中尽可能少做事情。在大多数情况下,可通过把操作转移到另一个线程或推迟操作来加快应用响应速度,这两种技术通常并不会使代码更难维护。把任务转移到另一个线程之前,一定要确保你已充分了解任务执行太慢的原因。若响应慢的原因是坏的算法或实现,就去修改它们,将任务转移到另一个线程只是欲盖弥彰而已。

  写程序时,应始终假定下列两种情况:

  1. 网络很慢(正在试图连接的服务器甚至可能没有响应)
  2. 文件系统的访问速度很慢

  结论就是,不应该在主线程内进行网络操作或访问文件系统,因为缓慢的操作会拖累系统的响应能力。虽然在开发环境中,你可能永远不会遇到任何网络问题或任何文件系统的性能问题,但用户可能不像你那么幸运。

 1.8 总结

  不要牺牲响应能力。这可能会加大应用开发的难度,而响应顺畅是应用成功的关键

2、NDK(native develop kit)入门

  Android的原生开发套件(NDK)是SDK的辅助工具,可用它把Android应用的一部分或全部用本地代码实现。字节码需由虚拟机解释,而本地代码可由设备处理器直接执行,没有任何中间步骤,执行速度更快,有时快很多。Dalvik的JIT编译器可将字节码编译为本地代码,减少应用字节码的解释次数(理想情况下仅有一次),而直接使用自己生成的本地代码,可让应用运行得更快。使用NDK时,是在开发环境中将代码编译为本地代码,而不是在Android设备上。

  使用本地代码和NDK的方式有以下两种:

  1. 应用的一部分用Java编写,另一部分用C/C++编写;
  2. 应用全部用C/C++写

2.1 处理器

  • ×86——Intel架构
  • armeabi——ARM架构,是Android设备的主导架构
  • MIPS——运行Android2.2的MIPS只能手机早在2011年6月就通过了Android兼容性测试,但官方Android NDK仍然不支持MIPS ABI

2.3 Application.mk

  Application.mk用于在指定整个应用的共同变量,Android.mk用来指定想构建什么模块以及如何构建

2.4 Android.mk是Android开发中,用来编译JNI代码的

  在开发工具中,new JNI 即可创建一个 android.mk文件;

  一个Android.mk文件可以编译多个模块,每个模块属下列类型之一:

  1. APK程序   一般的Android程序,编译打包生成apk文件

  2. JAVA库  java类库,编译打包生成jar文件

  3. C\C++应用程序 可执行的C\C++应用程序

  4. C\C++静态库 编译生成C\C++静态库,并打包成.a文件

  5. C\C++共享库 编译生成共享库(动态链接库),并打包成.so文, 有且只有共享库才能被安装/复制到您的应用软件(APK)包中。  

2.7 总结

  本章介绍了使用本地代码提高性能的办法。精心雕琢的本地代码很少会降低性能,而使用NDK的原因也不只是提高性能。下面总结了使用NDK的理由:

  • 重用现有代码,而不是在Java中重写一切;
  • 编写新的代码,在其他不支持Java的平台上使用;
  • 要在没有JIT编译器(Android2.1或更早版本)的旧Android设备上运行应用,那本地代码是提供顺畅用户体验的唯一出路;
  • 即使Android设备上已有JIT编译器,在应用中使用本地代码还是可提升用户体验。

  前两个原因非常重要,在某些情况下,你可能需要为了它们牺牲性能(前提是不会影响到用户体验,或至少不会超出用户的忍耐范围)和许多开发者一样,你可用的资源有限,若想让尽可能多的人采用你开发的应用,不要局限在单一平台,那不会使你的收益最大化。

3、NDK进阶

0 0
原创粉丝点击