android – Gradle和嵌套的非传递依赖项

这是一个测试项目:
click

我有一个测试Gradle Android项目有三个模块:app,library_a,library_b.应用程序依赖于library_a,然后library_a依赖于library_b:

build.gradle(app)

dependencies {
    ...
    compile (project(":library_a")){
        transitive = false;
    }
}

build.gradle(library_a)

dependencies {
    ...
    compile (project(":library_b")){
        transitive = false;
    }
}

请注意,我设置transitive = false,因为我不希望从app访问library_b中的类

每个模块只有一个类,代码非常简单:

应用:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        ClassA classA = new ClassA();
        classA.doSomething();
    }
}

library_a:

public class ClassA
{
    public void doSomething(){
        Log.i("Test", "Done A!");

        ClassB classB = new ClassB();
        classB.doSomething();
    }
}

library_b:

public class ClassB
{
    public void doSomething(){
        Log.i("Test", "Done B!");
    }
}

好吧,问题在于:我正在用gradlew构建我的项目. Apk正在成功编译,但是当我运行它时,我得到了NoClassDefFoundError.

I/Test﹕ Done A!
E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NoClassDefFoundError: ru.pvolan.library_b.ClassB
            at ru.pvolan.somelibrary.ClassA.doSomething(ClassA.java:12)
            ...

如果我在两个.gradle文件中设置transitive = true,它运行正常,但是,正如我上面提到的,我不希望依赖是可传递的,只要我不希望可以从MainActivity访问ClassB – 只有ClassA .

我究竟做错了什么?

最佳答案 问题是library_b是必需的依赖项.您不能简单地排除它,因为您需要它在运行时位于类路径上.您实际上是在歪曲您的实际依赖关系,以强制执行代码约定,从而失去利用Gradle等依赖关系管理系统的任何优势.如果你想强制执行类或包黑名单,我建议使用像PMD这样的源分析工具.这是将特定类列入黑名单的
an example规则.

如果由于某种原因无法做到这一点,您可以通过简单地将library_b添加到app的运行时类路径来使上述示例“工作”.

dependencies {
    runtime project(':library_b')
}
点赞