ProGuard可以从ALWAYS返回常量的方法中删除条件代码吗?

时间:2013-08-04 12:09:45

标签: android optimization proguard

在我的Android应用程序上,我一直在使用这样的条件代码:

if(BuildConfig.DEBUG) {
    // do something...
}

如果ProGurad将BuildConfig.DEBUG评估为false,则if内的代码块将从最终字节码中删除。这是按预期工作的。

然而,随着Android新构建系统的推出,我们现在拥有许多我们以前没有的能力。我正在通过创建一个新的buildType来利用它,我称之为 QA 。有了这个,我添加了一个BuildConfig.QA常量,它对应于构建类型将是真或假。

现在我有一些代码片段,我需要测试它是DEBUG还是QA版本,如下所示:

if(BuildConfig.DEBUG || BuildConfig.QA) {
    // do something...
}

但是在整个地方写这个很麻烦。相反,我决定在我的utils类上创建一个静态方法,如下所示:

public static boolean isDevelopmentBuild() {
    return BuildConfig.DEBUG || BuildConfig.QA;
}

问题是,使用这种方法,任何条件代码都不会像过去那样被删除。之前,ProGuard可以将这些常量评估为false并删除代码。现在,它必须调用一个方法并检查返回值。

但是由于该方法的返回值是常量,ProGuard是否有可能以一种知道返回值始终为常量值(在运行时)的方式评估方法调用并从最终中删除代码字节码?

2 个答案:

答案 0 :(得分:6)

为什么不在BuildConfig界面中添加常量DEV,比如

boolean DEBUG = ...
boolean QA = ...
boolean DEV = DEBUG | QA;

它将是一个编译时常量(假设在编译时定义了DEBUG和QA),因此ProGuard将能够基于

进行代码消除
if (BuildConfig.DEV) { ...

答案 1 :(得分:3)

ProGuard应该能够内联方法并删除调试代码。您可以使用像dexdump这样的Dalvik字节码反汇编器或反编译器轻松检查它。

欧内斯特弗里德曼 - 希尔的解决方案可能更可取。实际上,javac编译器已经删除了由设置为false的常量布尔标志保护的代码。它节省了一些处理,您不需要依赖ProGuard。同样,您可以使用反汇编程序或反编译器检查结果。