Gradle 实现与 API 配置

新手上路,请多包涵

我试图弄清楚 apiimplementation 配置在构建我的 依赖 项时有什么区别。

在文档中,它说 implementation 具有更好的构建时间,但是,在类似的问题中看到此 评论,我想知道这是否属实。

由于我不是 Gradle 方面的专家,希望有人能提供帮助。我已经阅读了 文档,但我想知道一个易于理解的解释。

原文由 reinaldomoreira 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 454
2 个回答

Gradle compile 关键字已弃用,取而代之的是 apiimplementation 关键字来配置依赖项。

Using api is the equivalent of using the deprecated compile , so if you replace all compile with api everything will works as always.

要了解 implementation 关键字,请考虑以下示例。

例子

假设您有一个名为 MyLibrary 的库,它在内部使用另一个名为 InternalLibrary 的库。像这样的东西:

 // 'InternalLibrary' module
public class InternalLibrary {
    public static String giveMeAString(){
        return "hello";
    }
}

 // 'MyLibrary' module
public class MyLibrary {
    public String myString(){
        return InternalLibrary.giveMeAString();
    }
}

假设 MyLibrary build.gradle api dependencies{} 5aa3142198e0bced351df296add1234bda043135b8373— 中使用配置

dependencies {
    api project(':InternalLibrary')
}

你想在你的代码中使用 MyLibrary 所以在你的应用程序的 build.gradle 你添加这个依赖:

 dependencies {
    implementation project(':MyLibrary')
}

使用 api 配置(或已弃用的 compile )您可以在应用程序代码中访问 InternalLibrary

 // Access 'MyLibrary' (granted)
MyLibrary myLib = new MyLibrary();
System.out.println(myLib.myString());

// Can ALSO access the internal library too (but you shouldn't)
System.out.println(InternalLibrary.giveMeAString());

这样,模块 MyLibrary 可能会“泄漏”某些东西的内部实现。您不应该(能够)使用它,因为它不是您直接导入的。

引入了 implementation 配置来防止这种情况。所以现在如果你在 --- 中使用 implementation 而不是 api MyLibrary

 dependencies {
    implementation project(':InternalLibrary')
}

您将无法再在您的应用代码中调用 InternalLibrary.giveMeAString()

这种装箱策略允许 Android Gradle 插件知道,如果您在 InternalLibrary 中编辑某些内容,它必须只触发 MyLibrary 的重新编译,而 不是 整个应用程序的重新编译,因为您无权访问 InternalLibrary

当你有很多嵌套依赖时,这种机制可以大大加快构建速度。 (观看最后链接的视频以全面了解这一点)

结论

  • 当您切换到新的 Android Gradle 插件 3.XX 时,您应该将所有 compile 替换为 implementation 关键字 \* (1 ) 。然后尝试编译和测试您的应用程序。如果一切正常,请保持代码不变,如果您遇到问题,您的依赖项可能有问题,或者您使用了现在私有且不易于访问的东西。 *Android Gradle 插件工程师 Jerome Dochez 的建议 (1 )

  • 如果您是库管理员,则应将 api 用于库的公共 API 所需的每个依赖项,而将 implementation 用于测试依赖项或不得由最终用户。

有用的文章 展示 实现api 之间的区别

参考(这是为节省时间而拆分的同一视频)

Google I/O 2017 - 如何加快 Gradle 构建速度(完整视频)

Google I/O 2017 - 如何加快 Gradle 构建速度(仅限新 GRADLE PLUGIN 3.0.0 部分)

Google I/O 2017 - 如何加快 Gradle 构建速度(参考 1 *)

安卓文档

原文由 MatPag 发布,翻译遵循 CC BY-SA 4.0 许可协议

请参考链接: Android Studio Dependency Configuration 可在 android 开发者的官方网站上找到。

在依赖项块中,您可以使用几种不同的依赖项配置之一声明库依赖项(例如上面显示的实现)。每个依赖项配置都为 Gradle 提供了有关如何使用依赖项的不同说明。

执行

Gradle 将依赖项添加到编译类路径并将依赖项打包到构建输出。但是,当您的模块配置实现依赖项时,它会让 Gradle 知道您不希望该模块在编译时将依赖项泄漏给其他模块。也就是说,依赖项仅在运行时对其他模块可用。使用此依赖配置而不是 api 或 compile(已弃用)可以显着缩短构建时间,因为它减少了构建系统需要重新编译的模块数量。例如,如果一个实现依赖改变了它的 API,Gradle 只会重新编译那个依赖和直接依赖它的模块。大多数应用程序和测试模块都应使用此配置。

api

Gradle 将依赖项添加到编译类路径和构建输出。当一个模块包含一个 api 依赖项时,它让 Gradle 知道该模块希望将该依赖项传递到其他模块,以便它们在运行时和编译时都可以使用它。此配置的行为与 compile 类似(现已弃用),但您应谨慎使用它,并且仅与需要传递到其他上游使用者的依赖项一起使用。这是因为,如果 api 依赖项更改了其外部 API,Gradle 会在编译时重新编译所有有权访问该依赖项的模块。因此,拥有大量 api 依赖项会显着增加构建时间。除非您想将依赖项的 API 公开给单独的模块,否则库模块应改为使用实现依赖项。

原文由 Islam Alshnawey 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题