Android 性能优化–Gradle 编译速度优化

news2025/1/18 6:15:51

Android 性能优化–Gradle 编译速度优化

  • 1. 保持工具最新
  • 2. 使用 KSP 代替 kapt
  • 3. 避免编译不必要的资源
  • 4. 优化 repositories maven 排序
  • 5. 在调试构建中使用静态构建配置值
  • 6. 使用静态依赖版本
  • 7. 创建库模块
  • 8. 为自定义构建逻辑创建任务
  • 9. 将图像转换为 WebP
  • 10. 禁用 PNG 处理
  • 11. 挑选 JVM 垃圾收集器
  • 12. 增加 JVM 堆大小
  • 13. 使用非传递 R 类
  • 14. 使用非常量 R 类
  • 15. 禁用 Jetifier 标志
  • 16. 使用配置缓存

最新更新地址 https://gitee.com/chenjim/chenjimblog

1. 保持工具最新

Android 工具几乎每次更新都会获得构建优化和新功能,保持最新版本可以加快构建速度
Android Gradle 插件
Android Studio 和 SDK 工具

2. 使用 KSP 代替 kapt

Kapt(Kotlin 注释处理工具)允许您将 Java 注释处理器与 Kotlin 代码结合使用,即使这些处理器没有对 Kotlin 的特定支持。这是通过从 Kotlin 文件生成 Java 存根来完成的,然后处理器可以读取这些存根。这种存根生成是一项昂贵的操作,并且对构建速度有重大影响。
KSP(Kotlin 符号处理)是 kapt 的 Kotlin 优先替代品。KSP 直接分析 Kotlin 代码,速度提高了 2 倍。它还可以更好地理解 Kotlin 的语言结构。
建议尽可能从 kapt 迁移到 KSP。在大多数情况下,此迁移只需要更改项目的构建配置。
如果你的项目使用了数据绑定(dataBinding) ,暂无无法迁移到KSP,尚未计划对 KSP 支持 , 可以通过将dataBinding的使用隔离到单独的模块来减轻 kapt 对构建的影响。
许多流行的库(比如 Glide、Room 等)都已经具有 KSP 支持,还有一些正在添加支持,比如 Dagger。
可参考 迁移KSP文档

3. 避免编译不必要的资源

避免编译和打包未测试的资源,例如其他语言本地化和屏幕密度资源。

android {
    productFlavors {
        create("dev") {
            // 如下配置显示 dev 渠道包,只打包 en 语言和 xxhdpi 屏幕密度的资源  
            resourceConfigurations("en", "xxhdpi")
}   }   }

或者如下修改

android {
    applicationVariants.configureEach { variant ->
        if (variant.buildType.name == "debug") {
            variant.mergedFlavor.resourceConfigurations.clear()
            variant.mergedFlavor.resourceConfigurations.add("zh-rCN")
            variant.mergedFlavor.resourceConfigurations.add("xxhdpi")
}     }    }

4. 优化 repositories maven 排序

如下图,可以查看到需要的依赖库下载结果

可以将多数能找到放最前面,比如在国内可以使用如下示例

repositories {
    maven { url 'https://maven.aliyun.com/repository/google' }
    maven { url 'https://maven.aliyun.com/repository/public' }
    maven { url 'https://your.private.io/repository' }
    mavenCentral()
    google()
}

5. 在调试构建中使用静态构建配置值

使用动态版本代码、版本名称、资源或任何其他更改清单文件的构建逻辑,
每次您想要运行更改时,都需要完整的应用程序构建,即使实际的更改可能只需要热交换。
如果 Release 版本确实需要,我们可以只跟改配置,使 debug 版本不生效。
比如在 BuildConfig 中版本号使用动态时间戳(精确到时分秒),导致小的修改,大编译,严重影响Rebuild速度。
在 Gradle 8.0 默认不生成 BuildConfig.java,进而无法直接引用 BuildConfig 中配置。

6. 使用静态依赖版本

在build.gradle文件中声明依赖项时,避免使用动态版本号
(末尾带有加号的版本号,如’androidx.appcompat:appcompat:1.+')
可能会导致意外的版本更新、难以解决版本差异以及 Gradle 检查更新导致的构建速度变慢。

7. 创建库模块

查找可以转换为 Android 库模块的代码。
以这种方式模块化您的代码,允许构建系统仅编译您修改的模块,并缓存这些输出以供将来构建。
模块化还可以使 并行项目执行更加有效

8. 为自定义构建逻辑创建任务

编译项目(Make Project)完成后,如下图,点击 Build Analyzer

会跳转到编译分析栏,会显示,Config 及 Task 执行时间,如下图

切换 OverviewTasks,可以显示各个 Task 执行耗时

创建构建配置文件后,如果构建配置文件显示相对较长的构建时间花费在 Configuration 阶段,
请检查您的build.gradle脚本,并查找要包含在自定义 Gradle 任务中的代码,
通过将一些构建逻辑移至任务中,您可以帮助确保任务仅在需要时运行,可以缓存结果以供后续构建使用

9. 将图像转换为 WebP

WebP 可以提供比 JPEG 或 PNG 更好的压缩。
减少图像文件大小而不必执行构建时压缩可以加快构建速度,特别是当您的应用程序使用大量图像资源时。
使用 Android Studio 可以 轻松 将图像转换为 WebP。

10. 禁用 PNG 处理

如果您不将 PNG 图像转换为 WebP,您仍然可以通过在每次构建应用程序时禁用自动图像压缩来加快构建速度。
如果您使用的是 Android Gradle 插件 3.0.0 或更高版本,则默认情况下,“debug”构建类型会禁用 PNG 处理。
如果 Release 也需要禁用 PNG 处理,可以参见如下修改

android {
    buildTypes {
        release {
            crunchPngs false
            //  isCrunchPngs = false //for kotlin
}   }   }

11. 挑选 JVM 垃圾收集器

通过配置 Gradle 使用的最佳 JVM 垃圾收集器可以提高构建性能。
虽然 JDK 8 默认配置为使用并行垃圾收集器,但 JDK 9 及更高版本配置为使用 G1 垃圾收集器。
建议 使用并行垃圾收集器测试您的 Gradle 构建,需要在 gradle.properties 添加如下修改
org.gradle.jvmargs=-XX:+UseParallelGC 或者 org.gradle.jvmargs=-Xmx4608M -XX:+UseParallelGC

12. 增加 JVM 堆大小

在 编译分析 栏,我们可以看到编译过程中,GC 花费的构建时间,
如果 超过 超过 15% ,我们可以增加 Java 虚拟机 (JVM) 堆大小
需要在 gradle.properties 中修改限制 4、6 或 8 GB ,参考如下
org.gradle.jvmargs=-Xmx6g

13. 使用非传递 R 类

使用非传递R类可以更快地构建具有多个模块的应用程序。
这样做可以确保每个模块的R类仅包含对其自身资源的引用,而不从其依赖项中提取引用,从而有助于防止资源重复。
这会带来更快的构建速度以及避免编译的相应好处。
这是 Android Gradle 插件 8.0.0 及更高版本中的默认行为。

14. 使用非常量 R 类

在APP模块和自动化测试时,使用非常量的 R.class 可以提高 Java 编译的增量并允许更精确的资源收缩。
在Library模块,R.class 一直不是常量,只有在打包APP或者自动化测试时,资源才被编号。
这是 Android Gradle Plugin 8.0.0 及更高版本中的默认行为,也就是如下代码会编译出错.

switch (viewId) {
    case R.id.bt_back:
        dosth1;
        break;
    case R.id.bt_enter:
        dosth2();
        break;
}

// 可以替换为  
if (viewId == R.id.bt_back) dosth1;
else if (viewId == R.id.bt_enter) dosth2();

15. 禁用 Jetifier 标志

由于大多数项目直接使用 AndroidX 库,因此您可以删除 Jetifier标志以获得更好的构建性能。
gradle.properties 修改如下即可
android.enableJetifier=false

16. 使用配置缓存

配置缓存 允许 Gradle 记录有关构建任务图的信息并在后续构建中重用它,不必再次重新配置整个构建。
可以在 gradle.properties 修改如下

org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=warn

注意可能会存在冲突的情况,参见 Gradle#13490
启用配置缓存后,第一次运行项目时,构建输出会显示
Calculating task graph as no configuration cache is available for tasks
在后续运行期间,构建输出显示
Reusing configuration cache

最新更新地址 https://gitee.com/chenjim/chenjimblog


参考文档
https://developer.android.com/build/optimize-your-build
https://developer.android.com/build/migrate-to-ksp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/884837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot3集成ElasticSearch

标签:ElasticSearch8.Kibana8; 一、简介 Elasticsearch是一个分布式、RESTful风格的搜索和数据分析引擎,适用于各种数据类型,数字、文本、地理位置、结构化数据、非结构化数据; 在实际的工作中,历经过Ela…

github中Keyless Google Maps API在网页中显示地图和标记 无需api key

使用Google Maps API在网页中显示地图和标记的示例博客。以下是一个简单的示例: C:\pythoncode\blog\google-map-markers-gh-pages\google-map-markers-gh-pages\index.html 介绍: 在本篇博客中,我们将学习如何使用Google Maps API在网页中…

MySQL— 基础语法大全及操作演示!!!(上)

MySQL—— 基础语法大全及操作演示(上) 一、MySQL概述1.1 、数据库相关概念1.1.1 MySQL启动和停止 1.2 、MySQL 客户端连接1.3 、数据模型 二、SQL2.1、SQL通用语法2.2、SQL分类2.3、DDL2.3.1 DDL — 数据库操作2.3.1 DDL — 表操作 2.4、DML2.4.1 DML—…

“记账”很麻烦,看这场竞赛中的队伍与合合信息是如何解决问题的

在我们日常生活中或多或少都会有记账的情况,以此来对自己的收支和消费习惯进行分析,来帮助自己减少不必要的开支,优化财务决策、合理分配资金,减少财务压力和不必要的浪费。 但记账这个动作本身就是一件比较麻烦的。虽然现阶段有…

【C语言】练习题专栏(9)

前言 今天是五道基础的选择题,包含一些简单的小知识,希望对大能有帮助。 1. 题干 答案 A\C\D 知识点 本题考察的知识点有两个:宏定义和typedef重定义。 宏仅仅是将INT_PTR替换成int * int *a,b其中,a的类型是int *而b为In…

如雷贯耳的话,不战而屈人之兵

如雷贯耳的话:不战而屈人之兵 【安志强趣讲《孙子兵法》第10讲】 【原文】 第三篇篇名:谋攻篇 【趣讲大白话】 胜负计算确定,物资钱粮准备好了,就开始制定战争谋略了。 【原文】 孙子曰:夫用兵之法,全国为上…

【Linux操作系统】举例解释Linux系统编程中文件io常用的函数

在Linux系统编程中,文件IO操作是非常常见和重要的操作之一。通过文件IO操作,我们可以打开、读取、写入和关闭文件,对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。 文章目录 1. open()1.1 原型、参数及…

C语言实例_奇偶校验算法

一、奇偶校验算法 奇偶校验算法(Parity Check Algorithm)是一种简单的错误检测方法,用于验证数据传输中是否发生了位错误。通过在数据中添加一个附加的奇偶位(即校验位),来实现错误的检测和纠正。 在奇偶…

BGP知识点整理

BGP相关知识点 定义 又名:边界网关路由协议 属于无类别路径矢量协议 EGP—外部网关路由协议-包含BGP IGP内部网关路由协议-包含RIP OSPF EIGRP IGP协议追求:1、无环(选路佳) 2、收敛快 3、占用资源少 EGP协议的追求: 1…

照耀国产的星火,再度上新!

国产之光,星火闪耀 ⭐ 新时代的星火⭐ 多模态能力⭐ 图像生成与虚拟人视频生成⭐ 音频生成与OCR笔记收藏⭐ 助手模式更新⭐ 插件能力⭐ 代码能力⭐ 写在最后 ⭐ 新时代的星火 在这个快速变革的时代,人工智能正迅猛地催生着前所未有的革命。从医疗到金融…

当众讲话培训的需求分析

标题:当众讲话培训的需求分析 摘要:当众讲话是现代社会中一项重要的技能,对于个人和职业发展都具有重要意义。然而,许多人面临着当众讲话的困难和挑战。本论文旨在分析当众讲话培训的需求,探讨为什么人们需要这种培训…

【Java基础】Java对象的生命周期

【Java基础】Java对象的生命周期 一、概述 一个类通过编译器将一个Java文件编译为Class字节码文件,然后通过JVM中的解释器编译成不同操作系统的机器码。虽然操作系统不同,但是基于解释器的虚拟机是相同的。java类的生命周期就是指一个class文件加载到类…

C#__使用委托升级冒泡排序

// 员工类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Delegate委托 {class Employee // 员工类{public string Name { get; set; }public double Salary { get; set; }public Employee…

二叉树的存储结构(链式存储)—— 数据结构与算法

😶‍🌫️Take your time ! 😶‍🌫️ 💥个人主页:🔥🔥🔥大魔王🔥🔥🔥 💥代码仓库:🔥🔥魔…

进行 200 瓦太阳能 (PV) 模块设计以测量太阳能光伏阵列的电压、电流和功率、综合负荷频率和电压控制系统的方法研究(Simulink实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

pycharm调整最大堆发挥最大

python程序运行时,怎么提高效率,设置pycharm最大堆过程如下; 一、进入设置pycharm最大堆; 二、进入设置pycharm最大堆; 如果8g设置为6g左右,占75%左右最佳

问题记录和细节补充

【问题记录】ORA-01400: 无法将 NULL 插入 Ajax 调用为Execute Server-Side Code返回了服务器错误ORA-01400: 无法将 NULL 插入 ("YWJA"."DEPT_TEST_WXX2"."DEPT_ID")。 原因:主键非自增,输入时并未有主键值传递&#x…

串是什么,串存储结构的3种实现方法

目录 串是什么,串存储结构的3种实现方法 串存储结构的具体实现 串的堆分配存储结构 串的块链存储结构 串是什么,串存储结构的3种实现方法 数据结构中,字符串要单独用一种存储结构来存储,称为串存储结构。这里的串指的就是字符…

判断Series序列是否含有空值NaN的Series.hasnans方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断Series序列是否含有空值NaN Series.hasnans [太阳]选择题 关于以下代码的说法中正确的是? import pandas as pd import numpy as np a pd.Series([1,np.nan],index["a","…

“想都是问题,干才是答案”是错误的,雷军说也不行

前几天,在为什么过去十年AI创业失败了一文中提了一个观点: “干就完了”式思维,是新式的刻舟求剑,剧毒,谁吃谁死。 没想到没过几天雷老板一个演讲又把这点炒到各个媒体的头条上,比如:“雷军20…