Android 性能优化总结

android 性能优化方法

  • android 性能优化方法
    • 性能优化的方向
    • apk 体积优化
      • 查看 apk 组成详情
      • 减小 res 里面的资源占用大小
      • 减小 so 库
      • 减小 dex 文件
    • apk 启动速度优化
      • 如何去测量一个应用的启动耗时
      • 如何优化 apk 启动时间
      • 遇到的问题

性能优化的方向

性能优化是移动端开发绕不过的一个问题,毕竟硬件资源有限,而且业务也越来越复杂,不优化的话体验很差,严重的话整个程序都可能无法运行。

网上已经有了很多关于性能优化的优秀文章,这里我也来小结下,算是对自己以前做的事情的总结吧。

首先,性能包含哪几个方便?然后,针对每一个方面,我们应该从什么入手来优化,如何去量化性能优化?

我们要先想清楚这几个问题,因为这样我们做性能优化才有一个清晰的目标,才知道需要朝哪几个方向去努力,通过可以量化的数值,我们才好判断说我们的优化取得的成果。

个人认为性能优化包含以下方面,没有列举完全,后续会补充。

  1. apk 体积优化。体积越小,下载越快、安装耗时越短。
  2. apk 启动速度,启动速度越快,体验越好。
  3. 内存的优化,即内存的合理使用和回收。
  4. 布局的优化,即层次和绘制速度优化。
  5. 电量优化等。

我们一个一个的来说。

apk 体积优化

这是一个比较容易量化的点,直接看编译后生成的 apk 的文件大小就好了。

查看 apk 组成详情

我们可以尝试把一个 apk 文件拖拽到 as 里面,你会看到如下图所示的内容。

可以看到占用资源比较多的是

  • res(一般多为 drawable)
  • so 库
  • dex 文件

我们可以从这三个方面来减少 apk 的体积

减小 res 里面的资源占用大小

一般 res 里面的文件比较多的是图片,像一些预置的图片啊啥的。因为要做到一些效果,所以这些图片不能轻易删除,虽然不能删除,但是我们可以用下面的方法来减少图片的文件大小从而减小 apk 的体积。

  • 用 jpeg 格式的图片替换 png 格式的图片,因为 jepg 压缩比更高,而且由于没有 alpha 通道,在内存里面可以通过设置参数,占用更少的内存。
  • 一些图标可以用 svg 格式的来替换原来的,由于 svg 图片是绘制出来的,不仅灵活,而且文件大小还很小。
  • png 和 jpeg 格式的图片还可以通过压缩工具压缩,可以进一步减少文件的大小,而且是效果明显的。

还有一种比较常见的方法是利用 as 的 lint 工具来扫描哪些资源是没有被使用的,没有被使用的资源可以删除,已减小 apk 的体积。一般由于业务和需求的变更和积累,多少都有些没有使用到的资源,用这个方法可以减小一部分的体积

还有一种方法就是利用微信开源的一款工具 AndResGuard。这个工具是一个资源混淆工具,原理是资源名称如果比较长的话,在编译到 apk 的过程中,这些文件名也是需要被记录的,通过资源名称混淆,我们可以减小文件名称的记录,从而达到减小文件大小的目的,同时也保护了我们的资源。

减小 so 库

so 库的话,没有特别的优化方法,但是有一些小技巧还是可以做的,如果你开发的 apk 只运行在 arm 平台上,你可以在编译脚本里面这样写

    ...
    defaultConfig {
        ...
        ndk {
            abiFilters "armeabi"
        }
    }
    ...

abiFilters 这个配置项会在打包 apk 的时候只编译指定平台的 so , 在上面的例子就是只打包 armeabi 下的 so 库。可配置项大概有下面几种

  • armeabi-v7a
  • armeabi
  • arm64-v8a
  • x86_64
  • x86

大家可以根据需要配置。配置后 apk 的体积一般会小一点

减小 dex 文件

dex 文件里面就是我们写的代码和一些第三方库的代码了,减少 dex 文件的大小就是减少代码了,我们可以通过下面几个方法来减少代码

  1. 减少第三方库的依赖,比如整个项目只用一个图片加载库,一个网络请求库。
  2. 对代码做混淆,不仅可以减小生成的字节码,同时还可以一定程度保护自己的源码。

对于第一条,没什么好说的,多个相同或者类似功能的库,不仅会导致生成的 dex 变大,同时在运行的时候是也会浪费一些资源,同时方法量也会上去,会导致 apk 方法数超过 65536 ,这是很得不偿失的做法。

对于第二条,混淆。混淆有许多好处,可以较大程度保护自己的代码,因为混淆后,一些类名、方法和属性都被修改为无意义的字母,别人反编译的时候也不容易看懂逻辑,同时代码混淆后的编译生成的字节码也会少一些。这样也达到了减小体积的目的。

apk 启动速度优化

启动速度应该是一个很重要的指标了,因为是用于使用 app 的第一印象,如果启动过慢,会给用户很不好的体验和印象,所以 apk 的启动速度优化还是很有必要的。app 的启动速度优化,网上有很多优秀的文章,《Android性能优化(一)之启动加速35%》、《一触即发——App启动优化最佳实践》 等,大家可以参考下。

这里我总结一下我平时工作中用到的方法吧。

如何去测量一个应用的启动耗时

有几种方法来测量一个应用的启动耗时,我们先来分析下冷启动(即启动之前没有 app 的进程)的过程

  1. Application 构造方法
  2. attachBaseContext()
  3. onCreate()
  4. 入口Activity的对象构造
  5. setTheme() 设置主题等信息
  6. 入口Activity的onCreate()
  7. 入口Activity的onStart()
  8. 入口Activity的onResume()
  9. 入口Activity的onAttachToWindow()
  10. 入口Activity的onWindowFocusChanged()

以上就是 app 冷启动过程。我们在第一个方法开始获取一个开始时间戳,然后最后一个方法结束获取一个结束时间戳,这两个时间戳的差就是这个应用的启动时间了。

还有一种方法来获取 app 的启动时间,那就是通过 adb ,你可以用下面的命令来启动一个应用,终端会打印出来启动时间的信息。

adb shell am start -W [PackageName]/[PackageName.MainActivity]

终端输入这个命令后,一般会打印类似下面的信息

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=PackageName/.MainActivity } 
Status: ok 
Activity: PackageName/.MainActivity 
ThisTime: 1818
TotalTime: 1818
WaitTime: 1829 
Complete

ThisTime 、 TotalTime 和 WaitTime 表示的时间如下所示

  1. ThisTime:一般和TotalTime时间一样,除非在应用启动时开了一个透明的Activity预先处理一些事再显示出主Activity,这样将比TotalTime小。
  2. TotalTime:应用的启动时间,包括创建进程+Application初始化+Activity初始化到界面显示。
  3. WaitTime:一般比TotalTime大点,包括系统影响的耗时。

通过这个方法我们也可以拿到 app 的启动时间。

如何优化 apk 启动时间

我们拿到 app 的启动时间后,只是知道了结果,我们需要分析过程,找出耗时的过程才好优化启动速度,所以我们如何获取详细的启动过程呢?

  • 使用第三方工具来帮助我们找到耗时操作,比如 Android Performance MonitorANR-WatchDog
  • 使用 Method tracingDDMS 来分析具体的信息

遇到的问题

在优化过程中主要遇到以下的问题

  1. Application 的 onCreate 方法里面做得事情太多,初始化了很多的 sdk 。

时间原因,后续补充

你可能感兴趣的:(Android-进阶)