我正在将Java项目从Ant迁移到Gradle。我认为最好的解决方案是使用Gradle的多项目支持,但我找不到摆脱循环依赖的方法。
原始项目设置为具有此布局:
String imageURL = new String("https://graph.facebook.com/" + accessToken.getUserId() + "/picture?type=small");
loadBitmap(imageURL);
globalMap.setOnMapLongClickListener(
// ...
// the same code without imageURL initialization and bitmap loading
);
- project/
- common/
- product-a/
- product-b/
,common
和product-a
之间的关系很棘手。 product-b
取决于common
或product-a
,具体取决于配置文件。同样,product-b
和product-a
依赖于product-b
,无论配置属性如何。 common
和product-a
永远不会同时建立。
我认为快速解决方案是在product-b
:
project/build.gradle
接下来,我想到了一种方法,让它更接近仅为project(':product-a') {
dependencies {
compile project(':common')
}
}
project(':product-b') {
dependencies {
compile project(':common')
}
}
工作。这让我想到了这个:
product-a
这会抛出一个带有循环依赖的异常。
我已经考虑通过设置project(':common') {
dependencies {
compile project(':product-a')
}
}
和product-a
/ product-b
所期望的类的接口或使用多态来重构common
和product-a
,但在我向前推进其中任何一个之前,有没有更好的方法来实现Gradle?我还没准备好摆脱这种技术债务。
答案 0 :(得分:7)
使用构建技巧无法解决删除循环依赖关系。您将不得不重构您的模块,因此不再存在循环依赖。从你的模块名称,没有其他信息,我认为你会想要提取" common"这取决于"产品 - *"并将其放入一个新的模块中。
答案 1 :(得分:0)
project(':project-a') {
dependencies {
compile project(':project-b')
}
}
project(':project-b') {
dependencies {
//circular dependency to :project-a
compile project(':project-a')
}
compileJava {
doLast {
// NOTE: project-a needs :project-b classes to be included
// in :project-a jar file hence the copy, mostly done if we need to
// to support different version of the same library
// compile each version on a separate project
copy {
from "$buildDir/classes/java/main"
include '**/*.class'
into project(':project-a').file('build/classes/java/main')
}
}
}
}
product-a-> build.gradle
/**
* Do nothing during configuration stage by
* registering a GradleBuild task
* will be referenced in the task compileJava doLast{}
*/
tasks.register("copyProjectBClasses", GradleBuild) {
//we'll invoke this later
def taskList = new ArrayList<String>()
taskList.add(":product-b:compileJava")
logger.lifecycle "Task to execute $taskList..."
setTasks(taskList)
}
// make sure :project-b classes are compiled first and copied to this project before
// all classes are added to the jar, so we do it after :project-a compiled.
compileJava {
doLast {
synchronized(this) {
// create temp file to avoid circular dependency
def newFile = new File("$buildDir/ongoingcopy.tmp")
if (!newFile.exists()) {
newFile.createNewFile()
GradleBuild buildCopyProjectBClasses = tasks.getByName("copyProjectBClasses")
buildCopyProjectBClasses.build()
}
newFile.delete()
}
}
}