android - 使用 Square 的 Wire 时出现 D8 异常
问题描述
在 Android 项目中添加 Square 的Wire库以支持 Protobuf 后,我在编译期间收到以下 D8 异常:
D8:程序类型已经存在:com.google.protobuf.DescriptorProto$ExtensionRange$ProtoAdapter_ExtensionRange
电线依赖:implementation 'com.squareup.wire:wire-runtime:2.2.0'
GradledependencyInsight
在我的项目中揭示了另一个依赖项,即传递引入com.google.protobuf.nano:protobuf-javanano:3.1.0
. 所以我添加了一个排除:
implementation ('com.google.vr:sdk-base:1.100.0'){
exclude group: 'com.google.protobuf.nano'
}
但这并没有解决问题。
是什么让 D8 悲伤,我怎样才能让它再次快乐?
更新
有问题的设置是:有 3 个模块A
, B
, C
. A
取决于B
和C
。B
并且C
都托管在内部 maven 服务器上,它们都依赖于wire-runtime
以下 POM 条目:
<dependency>
<groupId>com.squareup.wire</groupId>
<artifactId>wire-runtime</artifactId>
<version>2.3.0-RC1</version>
<scope>compile</scope>
</dependency>
我试过 Wire 版本 2.2 和 2.3.0。A
当只依赖B
或只依赖时,一切都是桃色的,但是当同时依赖和C
时,D8 会变得悲伤。A
B
C
那么你如何依赖于传递依赖于 Wire 的多个模块呢?
解决方案
D8伤心的原因
当您运行 Wire 代码生成时,它会在您的项目中创建一些 Java 源文件,所有其他 Wire 代码生成的代码都依赖这些文件。com.google.protobuf.DescriptorProto
就是这样一个文件。因此,当您依赖两个使用 Wire 的模块时,您将拥有两个模块,它们都包含具有相同名称和包的 Java 源文件,并最终得到重复的 .class 文件。这些 .class 文件是您的库模块打包输出的一部分(不是传递依赖项),因此没有任何gradle exclude
帮助(除非您知道一些我不知道的 Gradle 恶作剧?...)。
可能的解决方案
在库模块中设置打包选项以包含 java 源代码,以便您仍然可以编译,但在打包 aar 时排除 .class 文件。我试过这个,但无法使打包选项实际上排除 .class 文件。即使它有效,我也不喜欢这种方法,所以我放弃了它。
(没有尝试,可能有效)com.google.protobuf
将 Wire 生成的源文件捆绑到您自己的单独库中,以便它们成为传递依赖项。您可能希望在运行 Wire 后编写一个处理此过程的 gradle 任务,以免每次都手动移动这些文件。在您的应用程序中包含所述库的单个副本并用于gradle exclude
忽略传递。
最终这感觉时间同步太多了,我选择使用Protobuf Gradle 插件
推荐阅读
- java - 如何使用 Rest 和 Spring 安全性通过 ldap 登录 Angular?
- apache-spark - EMR 未检测到所有内存
- azure-sql-server - 使用在 Azure 中使用 MFA 的帐户调用 Sqlcmd
- java - 尝试通过球衣过滤器发送重定向并且页面不会刷新
- c# - Settings.Default.Settings.Save() 正在将空白值写入用户 appdata 文件夹中的设置文件
- python - 在 Python 中调用 Pyrebase 时出现未知语法错误
- java - 如何根据布局获取容器组件?
- redux - Redux 和 socket.io 无限循环
- jquery - 引导列无法切换隐藏/显示
- spring-boot - 使用自定义上下文 url 作为环境变量在 minkube 中启动 sprinboot