我有一个随着时间的推移而增长的Android项目,并且其大小已经增加了gradle构建时间。
当它低于65k的限制时 - 可以忍受 - 大约 14s 。 现在使用multidex需要 36s 。
所以我的问题是 - 是否有任何方法可以“关闭”未使用的代码部分,使其恢复到65k以下的限制?
例如关闭通过gradle引入的amazon s3 sdk并且有数以千计的方法。
我知道你可以用proguard删除代码,但这只会使构建时间更快。
我很高兴它在运行时崩溃,当我打开使用它的部件时,只是想让测试更快。
当我从gradle进口中删除亚马逊时,我显然得到了这个:
Error:(24, 26) error: package com.amazonaws.auth does not exist
有没有办法以某种方式忽略错误?我知道在Picasso中,它有一个运行时检查,看看你是否有OkHttp,如果你没有 - 使用标准网络。
static Downloader createDefaultDownloader(Context context) {
if (SDK_INT >= GINGERBREAD) {
try {
Class.forName("com.squareup.okhttp.OkHttpClient");
return OkHttpLoaderCreator.create(context);
} catch (ClassNotFoundException ignored) {}
}
return new UrlConnectionDownloader(context);
}
我能做到这样吗?或者其他任何方式?
答案 0 :(得分:3)
这样做的唯一现实方法(我意识到)是重构您的项目,以便将您的包拆分为单独的模块。因此,每个模块都有单独的gradle构建文件,但每次触摸时只需重新编译每个模块。例如,您可以拥有数据访问包和UI包。这似乎是一个非常自然的分裂。
我意识到这是一个令人失望的答案,但您抱怨的问题是您的构建依赖项需要所有这些额外的不必要的库和方法调用:而不是您的代码使用它们。
我能给你的另一个提示是Google Play API工具包有成千上万的方法调用。如果你只能使用你正在使用的碎片,你就有更好的机会低于65k的极限。
答案 1 :(得分:1)
可以单独为每个构建类型指定编译时依赖项。我使用此方法仅在发布版本中包含“仅限生产”的依赖项,从而减少了调试版本的方法计数。
例如,我只在发布版本中包含Crashlytics。因此,在build.gradle
中,我仅包含我的发布版本(以及测试版和alpha版)的依赖项:
releaseCompile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
transitive = true;
}
然后我将Crashlytics的功能抽象为一个名为CrashReportingService
的类。在我的调试源代码中,这个类什么都不做:
/应用/ SRC /的调试强> /java/com/example/services/CrashReportingService.java :
public class CrashReportingService {
public static void initialise(Context context) {
}
public static void logException(Throwable throwable) {
}
}
我在发布源代码中充实了实现:
/应用/ SRC /的释放强> /java/com/example/services/CrashReportingService.java
public class CrashReportingService {
public static void initialise(Context context) {
Fabric.with(context, new Crashlytics());
}
public static void logException(Throwable throwable) {
Crashlytics.getInstance().core.logException(throwable);
}
}
Crashlytics现在仅包含在发布版本中,并且在我的调试版本中没有引用Crashlytics。回到65k以下的方法,万岁!
答案 2 :(得分:0)
我有另一种选择。这也有助于加快但不是你的 需求。那是使用demon。
如果您使用Android(或Android Studio)的新Gradle构建系统,您可能已经意识到,即使是最简单的Gradle调用(例如gradle项目或成绩任务)也非常慢。在我的电脑上,这种Gradle电话花了大约8秒钟。如果告诉Gradle使用守护进程构建,可以减少Gradle的启动时间(在我的计算机上减少到两秒)。只需在以下目录中创建名为gradle.properties
的文件:
/home/<username>/.gradle/
(Linux)/Users/<username>/.gradle/
(Mac)C:\Users\<username>\.gradle
(Windows)org.gradle.daemon=true
从现在开始,Gradle将使用守护进程进行构建,无论您是从命令行使用Gradle还是在Android Studio中构建。您还可以将gradle.properties文件放在项目的根目录中,并将其提交到SCM系统。但是你必须为每个项目做这个(如果你想在每个项目中使用守护进程)。
注意:如果您没有使用Gradle构建任何东西一段时间(目前 3小时),它会停止守护进程,这样你就会经历很长时间 下一次构建的启动时间。
Gradle Daemon是一个长期存在的构建过程。在构建之间,它等待下一个构建。这有一个明显的好处,即只需要将Gradle一次加载到内存中进行多次构建,而不是每次构建一次。这本身就是一项重要的性能优化,但并非如此。
现代JVM性能的重要部分是运行时代码优化。例如,HotSpot(Oracle提供的JVM实现并用作OpenJDK的基础)在运行时对代码应用优化。优化是渐进的而不是瞬时的。也就是说,代码在执行期间逐步优化,这意味着后续构建可以更快地纯粹由于该优化过程。
使用HotSpot进行的实验表明它需要介于5之间 和10个构建优化稳定。差异在于 感知守护进程的第一个构建和第十个构建之间的构建时间 可能非常戏剧性。
守护进程还允许跨构建更有效地进行内存缓存。例如,构建所需的类(例如插件,构建脚本)可以在构建之间保存在内存中。同样,Gradle可以维护构建数据的内存缓存,例如任务输入和输出的哈希,用于增量构建。