我试图在Android Studio中进行条件构建,我可以通过删除任何多余的库依赖项来减少生成的APK的大小,如果特定分发不需要它们。
我有一些大致接近以下内容的代码:
public class MyClass {
/* Static Declarations. */
public static final boolean USE_LIBRARY = false;
public void doSomething() {
// Are we using the library?
if(MyClass.USE_LIBRARY) {
// Do something with the library that we'd define in my build.gradle.
com.some.gradle.library.MyLibrary.doSomethingWithLibrary();
}
else {
// Do something else.
}
}
}
如果从Gradle依赖项中删除com.some.gradle.library
,则会收到编译错误,指示无法编译上述代码。如您所见,如果USE_LIBRARY
仍为假,我们永远不需要提出任何参考MyLibrary
;甚至没有实例化,因为它没有提到进口;这些只是在运行时被侵占。
我应该注意到,在实践中,USE_LIBRARY
是一个以应用程序BuildConfig.java
为基础的程序生成的常量。
编译器当然可以确定可以优化此代码吗?这是一种我可以解决的预处理器检查吗?
答案 0 :(得分:2)
我试图在Android Studio中进行条件构建,我可以通过删除任何多余的库依赖项来减少生成的APK的大小,如果特定分发不需要它们。
步骤#1:为特定分布"定义产品风味。出于本答案的目的,我将称之为foo
。您还需要其他产品的其他产品口味。
步骤2:将引入此JAR的compile
语句更改为fooCompile
语句,以便仅在foo
版本中使用。
步骤3:在每种产品口味中都有一个版本MyClass
'源集(例如src/foo/java/
),其中foo
中的一个引用了库,而其他的则没有。
答案 1 :(得分:1)
我认为您可能会混淆Java运行时的行为并编译时间过程。
在运行期间,您的代码可以有条件地执行,并且可以忽略库调用,但在编译期间,所有代码都会被处理。
通过在编译时引用库,在编译时需要依赖项。
但是,有一个名为Proguard的实用程序,它是android构建系统的一部分,可以从apk中删除未使用的字节代码。另外,检查@CommonsWare的答案,如果您在不同的版本中根本没有使用该库,那么构建类型允许您创建没有该库的apk的单独版本
答案 2 :(得分:1)
找到解决方案。如果你可以保证在运行时没有库代码可以与之交互,那么上面我的方法是是可能的。这包括确保没有任何运行时类extend
作为库的一部分的任何父级或implement
接口。我能够使用ClassyShark验证代码是否已被清除。
"技巧"是将库组件声明为provided
,用于构建变体,您希望假装可以使用这些库,以及compile
当您希望导出库时
即。使用两个构建变体,libraryVariant
和emptyVariant
,它们通过USE_LIBRARY
以编程方式切换buildConfigField 'boolean', 'USE_LIBRARY', 'X'
的值。然后,您可以按如下方式定义依赖项:
dependencies {
// Actually package the library with the compiled APK.
libraryVariantCompile "com.some.gradle.library:-1"
// Ignore the library; just please the linting process.
emptyVariantProvided "com.some.gradle.library:-1"
}