当前位置: 首页 > 科技观察

Android优化APP构建速度的17条建议

时间:2023-03-13 01:10:16 科技观察

Android优化APP构建速度的17条建议时间已经成为开发瓶颈。本文结合谷歌官方文档和自己的一些理解,提供一些优化建议,以提高app构建速度。1.为开发环境创建变体。在准备应用的发布版本时需要进行许多配置,但在开发应用时不需要这些配置。启动不必要的构建过程会使你的增量构建或干净构建变得非常缓慢,因此有必要构建一个只保留开发所需配置的变体。以下示例创建了dev和prod变体(prod是发布版本的配置)。android{...defaultConfig{...}buildTypes{...}productFlavors{//当构建使用此flavor的变体时,以下配置//覆盖defaultConfigblock.dev中的那些{//为了避免使用legacymultidex,setminSdkVersionto21orhigher.minSdkVersion21versionSizeNameSuffic'{"pro"/如果您已经为您的应用程序的其他发布版本配置了默认配置块,//您可以将此块留空,Gradle使用//默认配置块中的配置。您仍然需要创建此风味。//否则,所有变体都使用“开发”风味配置。Locallanguageandscreendensityresources),你可以在你的'dev'flavor下只指定一种语言和一种屏幕密度,如下:android{...productFlavors{dev{...//下面的配置限制了“dev”flavorousing//Englishstringresourcesandxxhdpiscreen-densityresources.resConfigs"en","xxhdpi"}...}}以上配置将限制dev变体仅使用英文字符串资源和xxhdpi屏幕密度资源。3.将调试版本的Crushlytics配置为不可用。在调试构建状态下,如果不需要运行崩溃报告,可以将此插件设置为不可用以提高构建速度,如下:android{...buildTypes{debug{ext.enableCrashlytics=false}}的以上只是一个例子。Crushlytics是一个崩溃报告分析工具。我们在开发的时候可能不需要,所以不需要打开。我们在实际开发中,如崩溃上报SDK、数据统计SDK等(如友盟统计、GrowingIO、百度统计)在开发阶段都设置为不可用,以提高构建速度。4.使用静态构建配置值构建调试版本通常,在调试构建中使用静态/硬编码值进行清单或资源配置。如果您的清单或资源文件值需要在每次构建时动态更新,那么InstantRun无法执行代码交换——它必须重建并安装新的APK。例如,使用动态版本代码、版本名称、资源或其他更改清单文件的构建逻辑,每次要执行修改时都会构建整个APK,即使实际修改可能只需要热插拔.如果这些构建配置需要动态配置,请将它们与您的发布构建变体分开,并在您的调试构建中保留它们的静态值。像下面build.gradle文件显示的这样:intMILLIS_IN_MINUTE=1000*60intminutesSinceEpoch=System.currentTimeMillis()/MILLIS_IN_MINUTEandroid{...defaultConfig{//MakingeitherofthesetwovaluesdynamicinthedefaultConfigwill//requireafullAPKbuildandreinstallationbecausetheAndroidManifest.xml//mustbeupdated(whichisnotsupportedbyInstantRun).versionCode1versionName"1.0"...}//上面的默认配置值是固定的,所以你的增量构建不需要//重新构建清单(因此整个APK,构建时间变慢)。//但是对于发布构建,没关系。所以下面的脚本遍历//所有已知的变体,找到那些是“发布”的构建类型,和//将那些属性更改为动态的东西。应用程序变体->如果所有{var(variant.buildType.name=="release"){variant.mergedFlavor.versionCode=minutesSinceEpoch;variant.mergedFlavor.versionName=minutesSinceEpoch+"-"+variant.flavorName;}}}5.构建时使用静态版本依赖声明时.gradle文件中的依赖项,你应该避免在末尾使用+号版本号,如:com.android.tools.build:gradle:2.+由于Gradle的检查更新,使用动态版本号会导致版本更新未知,导致版本差异难以解决,构建速度变慢。您应该改用静态或硬编码版本号。如:com.android.tools.build:gradle:2.2.2。6.使按需配置启用状态为了让Gradle准确地知道如何构建你的APP,在每次构建之前,构建系统配置项目的所有模块和其他依赖项(即使你只想构建或测试一个模块),这使得大型多模块项目的构建速度非常缓慢。要告诉Gradle仅配置您要构建的模块,请通过执行以下操作启用按需配置:(1)从菜单栏中选择文件->设置(Mac上为AndroidStudio->首选项)(2)导航到Build,Execution,Deployment->Compiler(3)勾选Configureondemand复选框(4)点击OK如图:on_demand.png7。创建一个librarymodule来检查你app中的代码,并将模块化的代码提取到一个AndroidLibrarymodule中,以这种方式模块化你的代码将允许构建系统只编译那些发生变化的模块,并缓存构建结果以供后续使用建立。按需和并行项目执行(projectparallelexecution)的相同配置会更高效(当你打开这些特性时)。8.CreateTasksforcustombuildlogic在你创建了buildprofile之后(buildprofile会在后面讨论),如果显示有相当长的一部分构建时间花在了“configureproject”阶段,那么请检查你的build.gradle脚本,并查找可以包含在自定义Gradle任务中的代码。通过将一些构建逻辑移动到任务中,它会在需要时运行。结果可以缓存起来供后续构建使用,并且这个构建逻辑可以并行执行(如果你开启了项目的并行执行),更多细节请阅读Gradle官方文档。Gradle官方文档提示:如果你的构建包含大量的自定义任务任务,您可能想要清理您的构建。gradle文件,通过自定义任务类(即自定义Gradle插件)将你的类添加到project-root/buildSrc/src/main/groovy/目录下,Gradle会自动将它们包含在项目的类路径中所有build.gradle文件。9、配置dexOptions并启用librarypre-dexing(dex预处理)首先补充一个知识点:Dex-in-process:新发布的AndroidStudio2.1新增了一个特性:DexInProcess,可以大大加快重新编译的速度,并提高InstantRun的性能。(第10条优化建议会提到)详情请看FasterAndroidStudioBuildswithDexInProcessAndroid插件提供了dexOptions脚本块,所以你可以配置相应的DEX构建特性,可以提高构建速度:(1)preDexLibraaies:声明是否对依赖库进行dex预处理,让你的增量构建更快,因为这个特性可能会让你的cleanbuild速度变慢,所以你可能希望在你的持续集成服务器上关闭这个特性。(2)maxProcessCount:设置运行dex-in-process时使用的最大线程数,默认值为4。(3)javaMaxHeapSize:设置DEX编译器的最大堆大小。与设置此属性相比,您应该增加Gradle堆大小(当dex-in-process可用时,此堆大小对DEX编译器有效)示例:android{...dexOptions{preDexLibrariestruemaxProcessCount8//而不是设置堆大小为DEX进程,增加Gradle的//heapsizetoenabledex-in-process.Tolearmmore,readthenextsection.//javaMaxHeapSize"2048m"}}你应该增加他们的值来测试这些设置,然后通过profile观察效果。当你为这个过程分配太多资源时,你可能会得到负面影响。10.增加Gradle的堆大小并启用dex-in-processDex-in-process允许多个DEX进程在单个VM中运行,这使得增量构建和清理构建更快。默认情况下,使用AndroidStudio2.1或更高版本创建的新项目会分配足够的内存来启用此功能。如果您没有使用AndroidStudio2.1或更高版本创建项目,则需要将Gradle守护进程设置为至少1536MB的堆大小内存。默认如下:gradle_heap.png以下示例在gradle.properties中设置Gradle堆内存大小为2048MB:org.gradle.jvmargs=-Xmx2048m//设置Gradle堆内存大小为2G在一些大型项目中,分配给Gradleheap更多的内存当然是有益的。但是,如果您使用的是内存较低的机器,则可能需要将IDE配置为内存较少。想知道如何更改分配给IDE的资源量以及Gradle对构建性能的影响,请参阅分析您的构建这篇文章。如果您在Modulebuild.gradle文件中为android.dexOptions.javaMaxHeapSize定义了一个值,那么您需要将Gradle堆大小设置为比javaMaxHeapSize多512MB,至少为1536MB。例如:在build.gradle中设置javaMaxHeapSize`为1280MB,那么你需要设置Gradle堆大小至少为1792MB(1280+512),当然设置大一些更好。build.gradle:dexOptions{javaMaxHeapSize"1280m"}gradle.properties:org.gradle.jvmargs=-Xmx1792m11。将图像转换为WebP格式WebP是一种提供有损压缩的图像文件格式,与JPEG和PNG一样具有相同的透明度支持,但同时它的压缩质量优于JPEG或PNG,减少了图像文件的大小而不在构建时对其进行压缩,因此可以提高构建速度,尤其是当您的APP使用大量图像资源时。但是有一个问题,在解压WebP格式的图片时,你的设备的CPU占用率会略有增加。使用AndroidStudio可以很方便的转换WebP格式。有关详细信息,请参阅将图像转换为WebP。Tips:另外,将项目中的图片转为webP格式也是优化APK大小的一个方向。Androidnative4.0支持webp是的,它可以提供与JPEG和PNG相同质量的图像但尺寸更小。没有任何合适的问题。12.禁用PNG压缩如果你不能(或不想)将你的PNG格式图像转换为WebP,你仍然可以通过在每次构建应用程序时禁用图像自动压缩来提高构建速度。要禁用此优化,请在build.gradle中添加以下代码:android{...aaptOptions{cruncherEnabledfalse}}13.使用InstantRunInstantRun通过推送某些代码和资源更改而无需构建新应用程序,从而显着减少更新应用程序的时间,并且在某些情况下,即使不重新启动当前活动,也可以在代码更改后通过单击ApplyChanges(黄色?图标)来使用InstantRun。当您执行以下操作时它会默认打开:使用调试构建变体Gradle插件版本2.3.0或更高版本构建您的应用程序在模块级别的build.gradle中将minSdkVersion设置为15或更高版本发布您的应用程序运行在Android5.0(API级别21)或更高级别,然后单击Run14。在构建项目时,使用构建缓存来存储由AndroidGradle插件生成的某些工件(例如AAR包和预dexed远程依赖项)。).当您使用缓存时,您的干净构建会更快,因为构建系统的后续构建可以简单地重用它们的缓存而无需重新创建它们。使用AndroidGradlePlugin2.3.0或更高版本的新项目将默认启用构建缓存(除非您手动禁用它)。有关更多信息,请阅读使用构建缓存加速干净构建.15。在可以增量构建Gradle2.1Java之后禁用注释处理器。使用注释处理器时,增量构建不可用。如果可以,请避免使用注释处理器,这样您就可以从仅构建更改的类中获益。(改善编译时间)16.Profileyourbuild在大型项目(或实现大量自定义构建逻辑)中,可能需要对构建过程有更深入的了解以找到瓶颈。您可以分析您的构建生命周期每个gradle任务在周期的每个阶段执行所花费的时间。例如:如果您的构建配置文件显示Gradle花费大量时间配置您的项目,这表明您需要将自定义构建逻辑移出配置阶段。另外,如果mergeDevDebugResources任务消耗了大量构建时间,则意味着你需要将图像转换为WebP格式或禁用PNGCrunching(优化建议11、12)。通过构建分析来提高你的构建速度通常需要在分析中打开运行你的构建而不做任何更改,多次修改构建配置,分析并观察结果的变化。生成和查看构建配置文件,执行以下步骤:1)、用AndroidStudio打开项目,选择View->ToolWindows->Terminal打开命令行2)、执行cleanbuild并输入以下命令,当你分析你的构建,每次构建之间都需要一个干净的构建,因为Gradle会跳过输入没有改变的任务,所以没有改变输入的第二个构建通常会运行得更快,因为任务不会在构建之间重新运行运行一个cleantask确保您分析了整个构建过程。//如果在Mac或Linux上使用./gradlewgradlewclean3),选择其中一种productflavors(productflavor)执行debugbuild,例如:devflavor,如下:gradlew--profile--recompile-scripts--offline--rerun-tasksassembleFlavorDebug命令解析:--profile:启用profiling--recompile-scripts:强制脚本重编译跳过缓存--offline:禁止Gradle获取离线依赖,这是为了确保任何延迟都是Gradle尝试引起的更新依赖关系,而不是误导您的分析数据。您应该先准备构建项目,以确保下载Gradle并缓存依赖项。--rerun-tasks:强制Gradle返回所有任务并忽略任何任务优化。4)、构建完成后,在project-root/build/reports/profile/目录下:profile_build.png5)、右键profile_timestamp.html,选择在浏览器中打开,会看到如下图,您可以观察报告中的每个选项卡以了解您的构建,例如TasksExecution显示每个任务的执行时间。profile_in_brower.pngtaskExecution显示每个任务的执行时间,如下图:task_execution.png6),可选:在对Project或构建配置进行任何更改之前,重复步骤3几次,但去掉--rerun-tasks标志,因为Gradle试图通过不重新执行输入未以任何方式修改的任务来节省时间(它们在TaskExecution选项卡下标记为UP-TO-DATE,如下所示:),您可以识别哪个任务不会执行,例如,如果:app:processDevUniversalDebugManifest未标记为UP-TO-DATE,则意味着您的构建配置会在每次构建时动态更新Manifest文件。但是,有些任务还是需要每次都执行,例如::app:checkDevDebugManifestprofile_up_to_date.png现在,你有了一个构建分析报告,你可以通过观察构建报告的每个选项卡开始寻找优化机会,一些构建配置是需要进行实验,因为它们在不同的项目或工作空间中的收益不同。例如,基于大量代码的大型项目可能会受益于使用混淆、清理无用代码和减小APK大小。但是,小型项目可能会受益于关闭混淆(混淆仍然很耗时)。此外,增加或减少具有第三个内存的机器上的Gradle堆大小也可能会产生相反的效果。17、项目组件化对于大型项目,以上优化建议可能会有一定的效果,但是构建速度还是有点慢,这时可以考虑构建组件,将项目拆分成一个个的组件,每个开发环境每个模块都是一个APK。发布时,每个模块都是一个库,供主项目使用。篇幅有限,这里就不详细介绍组件化了。现在组件化是一种趋势。如果你有精力或者实力,组件化是一个非常好的选择。最后,以上是解决app构建速度慢的一些优化建议。如果你觉得你的项目构建速度慢,可以试试这些优化项。有什么问题欢迎在评论区留言。如果大家有更好的优化建议,也可以在下方留言,我会补充在文末。参考OptimizeYourBuildSpeedGradle