Android Apk 大小分析 (一)精简版

最近在做一个项目,由于 app 是运行与小型 Android 设备上,对 apk 的启动速度和 apk 大小有一定需求,要求 apk 越精简越好,也就是越小越好。

但是我一开始,并没有注意这个问题,引入了很多的库,等项目开发完毕后,发现 debug apk 有 19MB 多,Release 版本有 15MB 多。此时并没有开启Minify这显然是不符合条件的。但是,开启了 Minify后出现很多的报错,怎么解决都解决不完,索性就直接重新新建项目来研究一下 apk 的大小问题。

场景一:只有一个基础 Activity 的 apk 有多大?

我打算采用两种方式来进行测试,一种是 kotlin 语言,一种是 java 语言。首先我们使用 kotlin。
需要注意的是,我们的app 的 gradle 中没有引入任何库,并且在 gradle 中开启了 minifyEnable 和 shrinkResources。gradle中关键信息如下:
image
image

1. Kotlin方式

1.1 基础 Activity 版本 apk

首先,我们使用 kotlin 语言进行一次测试,我们编写一个简单的界面然后,编译出 Release 版本的 apk,分析一下其大小。
image
采用原生 Activity,没有导入和使用任何第三方库的情况下,采用 kotlin 语言,我们运行./gradlew assembleRelease 看看编译出的 apk 有多大。
答案是 60KB 左右。
image
那么我们用ide 打开 apk 看一下里边的内容如下:
image
我们可以看到,60KB里边的大部分是res 目录,也就是应用的 logo,kotlin 引入的文件夹和相关文件大约占用了 10.5KB,而 classes.dex 只占用了 524 Byte,amazing!!
那么我们来看看 dex文件中有哪些内容:
image
我们可以看到,只有最基础的一个 Activity 界面,以及对 Activity 的三个方法的引用。占用空间非常小。

我把所有 logo 都删掉,只保留一个 8kb 的高清 logo,放到 drawable 文件夹中,然后修改 manifest
image
然后我们再次打包 Release apk,效果如下:
image
Boom!!!!!! apk 尺寸降低到了 25KB!!! Amazing !!!!
image
打开 apk,我们可以看到,删掉logo 文件后显著减少了 res容量。那么我们来横向对比一下 纯Java 方式打包的 apk 有多大。

2. Java

2.1 基础 Activity 版本 apk

只有 Activity ,全量 logo 情况下,答案是 47KB,那么我们看看内部组成:
image

我们可以看到,首先,他没有 10.5KB 左右的 kotlin 文件夹,res 目录和 kotlin 是一样的, 所以总体相比 kotlin 版本减少了11KB 左右,由此我们可出结论,kotlin 版本 apk 至少会增加 11KB 左右的 Kotlin 标准库的内置信息和元数据文件 文件夹。

那么同理如果我们把 logo 去掉呢,最小的 Java 版本 apk 是多少呢?答案是:8KB,内容如下:
image

场景二:引入androidx.appcompat库,并将 Activity 替换为 AppCompatActivity

我们在场景一的基础上,引入androidx.appcompat,并且只将 Activity 替换为 AppCompatActivity, 此时编译出来的 apk 有多大呢?不管是 Kotlin 还是 Java, apk 的大小都达到了 680 KB左右,也就是说,androidx.appcompat直接引入了 670KB 左右的内容大小。我们打开 apk 看一下:

  • Kotlin 版本:
    image

  • Java 版本:
    image
    java 版本这里有意思的一点是,引入后,他的 apk 中也出现了 kotlin 的文件夹,我猜测是androidx.appcompat是kotlin 编写的,所以,引入他也导致了引入了 kotlin 依赖。

也就是说我们在上一章节中抠抠搜搜去掉的二三十 KB 的空间,在引入了一个三方库后,显得十分可笑。不过这里需要知道的是 appcompat 是一个非常大的库。以下是 Gemini 解释的 androidx.appcompat:appcompat 的作用。

您引用的这个依赖:

appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }

指的是 androidx.appcompat:appcompat 库,它是 Android Jetpack 库中 最核心、最重要的库之一

1. appcompat 包的作用是什么?

appcompat 的核心作用是提供 向后兼容性现代 UI 功能,允许您的应用在旧版本的 Android 设备上使用最新的功能和设计标准(特别是 Material Design)。

具体来说,它提供了以下关键功能:

  1. 向后兼容性 (Backwards Compatibility)
    • 允许您在旧版本的 Android 系统上(通常一直兼容到 API 级别 21,甚至更低)使用新版 API 中引入的许多功能和类。
    • 例如,它提供了 AppCompatActivityAppCompatButtonAppCompatTextView 等,这些类在底层处理了不同 Android 版本之间的差异。
  2. 核心 UI 组件
    • 提供了核心的 UI 基础结构,例如:
      • ActionBarToolbar:允许在所有支持的 API 级别上使用操作栏或工具栏。
      • Material Design 风格:即使在旧设备上,也能通过使用 Theme.AppCompat 系列主题来获得一致的 Material Design 视觉效果。
      • 资源和主题兼容:对颜色、矢量图 (Vector Drawables) 和主题属性进行向后移植,确保它们在所有设备上都能正确渲染。
  3. Fragment 支持
    • 它通常还会传递依赖 androidx.fragment 库,为管理屏幕片段(Fragment)提供兼容的 API。
  4. 夜间模式 (Night Mode) 支持
    • 提供了 AppCompatDelegate 来支持在各种 Android 版本上切换应用的深色/夜间主题。

简单来说: 只要您的应用想要在广泛的 Android 设备上运行,并且想要使用 Material Design 和现代的 Android UI 最佳实践,那么 appcompat 是几乎必不可少的


2. 它很大吗?

在 Android 依赖库中,appcompat 库相对来说是比较大的。

  • 大小估算:根据一些公开的讨论和 Issue 追踪(例如 Google Issue Tracker),如果一个项目只添加了 appcompat 库(且没有开启代码混淆/收缩),可能会导致 APK 大小增加约 700 KB 到 800 KB 甚至更多
  • 原因:它体积大的原因是它不是一个简单的工具类库,而是包含了大量的 兼容性代码、资源文件(如各种版本的颜色、主题、矢量图等),以及一套完整的 UI 框架,以便在旧设备上模拟新版系统的行为。
  • 实际影响
    • 开启 R8/ProGuard/资源收缩后:在实际的 Release 构建中,如果您开启了 R8(代码和资源收缩),R8 会移除所有未被使用的兼容性代码和资源,因此 appcompat 最终对 APK 大小的贡献会大幅减小

结论appcompat 是一个功能强大且必要的库。虽然它在原始 JAR/AAR 文件中体积较大,但在优化后的 Release APK 中,它的实际影响是可以接受的,而且它带来的兼容性和功能性价值远超其体积。

posted @ 2025-10-17 11:01  Greg_LYU  阅读(27)  评论(0)    收藏  举报