我想我的问题很常见.我有一个相当大的gradle代码库,我使用产品风格生成自定义版本.这些产品口味通常需要一个或多个类的定制版本src\main\java.
我已经阅读了Gradle文档,并且在查看同一个问题时也遇到了以下问题:
使用Build Flavors - 正确构建源文件夹和build.gradle 为同一类的不同版本构建flavor
我明白为什么你不能src\main\java在你的口味中定义相同的类,但是将类从src\main\java你的产品风格转移到你的产品风味中的解决方案有一个相当大的缺点.当您将类移动src\main\java到最新版本以进行自定义时,您还需要将该类的原始非自定义版本的副本移动到其他所有以前的产品类型中,否则它们将不再构建.
您可能只需要每次从原始文件调整一个或两个不同的类(然后必须将这些类重新分配到flavor目录),但随着时间的推移,移动的类的数量将会生成,剩余的数量src\main\java将减少每个类你必须这样做的时间.最终,大多数类都会有各种风格(即使大多数类都是原件的副本)并且src\main\java几乎是空的,有点打败了整个Gradle构建结构的目的.
此外,您需要保持每次开始新口味时可以克隆的"默认"风格,因此您知道根据原始代码库开始使用所有类.
使用BuildConfig中的字段来定义是否应该使用自定义类:
buildConfigField 'boolean', 'CUSTOM_ACTIVITY_X', 'true'
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用以下代码:
final Intent intent = new Intent();
...
if (BuildConfig.CUSTOM_ACTIVITY_X) {
intent.setClass(ThisActivity.this, CustomActivityX.class);
} else {
intent.setClass(ThisActivity.this, DefaultActivityX.class);
}
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
每种风味仍然需要一个副本CustomActivityX,但它可以只是一个虚拟的空类,你知道它不会被使用.这意味着您的默认版本的类始终保留在src\main\java.
虽然试图摆脱对其他所有风格的虚拟CustomActivityX的需求,但我已经看过了Class.forName().
例如:
final Class activityX;
if (BuildConfig.CUSTOM_ACTIVITY_X) {
try {
activityX = Class.forName("CustomActivityX");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
activityX = DefaultActivityX.class;
}
final Intent intent = new Intent();
...
intent.setClass(ThisActivity.this, activityX);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
但是,当您尝试使用它时,这显然会导致"activityX可能尚未初始化",因为该try/catch块.
怎么能克服???
因此,这里有两个问题:1)您主要解决方法中的编码错误2)您要解决的更广泛的问题。
我可以在第一个问题上提供比第二个问题更多的帮助。您需要做的就是初始化变量。您问“如何克服???” 我相信这可以解决问题:
Class activityX = null; //remove 'final' and initialize this to null, then null-check it later
if (BuildConfig.CUSTOM_ACTIVITY_X) {
try {
activityX = Class.forName("CustomActivityX");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
activityX = DefaultActivityX.class;
}
final Intent intent = new Intent();
...
if(activityX != null) {
intent.setClass(ThisActivity.this, activityX);
startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)
现在,关于您要解决的更广泛的问题,很明显,上面的代码有一些代码味道,这表明可能有更好的方法。我使用了特定于风味的类,而不必将其复制到所有其他风味中。在那些情况下,其他类型的代码不会执行依赖于这些类的代码。例如,想象一个“付费”版本,其中“免费”版本根本不会加载某些可供付费用户使用的类。
因此,我认为只有在所有口味都尝试加载相关类时才会出现此问题。在不了解您的整体代码库的情况下,很难提出替代方案。但是,我建议您尝试使用继承,抽象类或接口来解决您的问题。
我要调查的第一件事:活动是否真的是您需要覆盖的最小代码/行为单元?我怀疑不是。也许您可以创建一个包含所有样板代码的BaseActivity,然后将风味特定的代码隔离到需要它的确切组件中。
例如,我使用的一种常见模式是通过XML文件处理这种事情。这样,活动和片段始终可以在各种口味中具有相同的行为,但是它们会加载不同的布局。这些布局包含自定义视图组件(它们从公共接口或抽象父类扩展,从而允许活动对该接口进行编码)。现在,不需要某些类的调味料将永远不会尝试加载它们,因为它们不存在于由该特定调味料装载的布局中。
无论如何,我希望这会有所帮助。如果不了解代码库的细微差别,很难解决更广泛的问题。我的建议是从根本上重新考虑事情,并尝试使类加载器远离需要加载特定于风味的类的需求。
| 归档时间: |
|
| 查看次数: |
3474 次 |
| 最近记录: |