android - Dagger 不能创建对象图,尽管它可以生成点文件

标签 android dependency-injection proguard dagger

我在现有应用程序中努力设置 Dagger (1.0.1)。它被配置为使用 ProGuard,但我使用 -dontobfuscate 将其禁用以进行此测试。

当我启用 dagger-compiler 时,它能够成功生成带有依赖关系图的点文件,但是当我删除编译器并在 Release 模式下构建应用程序时,它会在启动期间崩溃,并提示它无法创建对象图。

java.lang.RuntimeException: Unable to start activity 
  ComponentInfo{com.corp.myapp/com.corp.myapp.ui.activity.MainActivity}: 
  java.lang.IllegalStateException: Errors creating object graph:

No injectable members on com.corp.myapp.core.services.ConnectionMonitor. Do 
  you want to add an injectable constructor? required by 
  com.corp.myapp.core.services.ConnectionMonitor 
  com.corp.myapp.ui.activity.MyAppBaseActivity.connectionManager

No injectable members on com.corp.myapp.ui.crouton.CroutonManager. Do you want 
  to add an injectable constructor? required by 
  com.corp.myapp.ui.crouton.CroutonManager 
  com.corp.myapp.ui.activity.MyAppBaseActivity.croutonManager

No injectable members on com.corp.core.assembler.ResourceAssembler. Do you want 
  to add an injectable constructor? required by 
  com.corp.core.assembler.ResourceAssembler 
  com.corp.myapp.ui.activity.MyAppBaseActivity.resourceAssembler

我看到 MyAppBaseActivity 并且它与 CroutonManagerConnectionMonitor 的依赖关系显示在生成的点文件中,因此根据 this comment我希望这能奏效。据我所知,如果有问题,我用来生成点文件的启用编译器的构建应该会检测到它。


更新:

我之前说过

In Debug mode it never fails

但经过进一步测试后情况并非如此:在Debug 模式下它不会因为 ProGuard 被禁用而失败,而在 Release 模式下它默认启用。如果我在 Release模式下构建应用程序但跳过 ProGuard,我也不会收到错误并且应用程序会成功启动。所以问题肯定与我的 ProGuard 配置有关。

最佳答案

Dagger 很大程度上依赖于反射和类名,这些名称是硬编码的并作为字符串进行操作。这使得代码难以收缩/优化/混淆。

以下配置适用于示例 dagger/examples/simple in Dagger 1.1.0 :

-keepattributes *Annotation*

-keepclassmembers,allowobfuscation class * {
    @javax.inject.* *;
    @dagger.* *;
    <init>();
}

-keep class **$$ModuleAdapter
-keep class **$$InjectAdapter
-keep class **$$StaticInjection

-keepnames !abstract class coffee.*

-keepnames class dagger.Lazy

配置保留所有带有 javax.injectdagger 注释的字段和方法,以及所有无参数构造函数。如果它们看起来未使用,ProGuard 可能会以其他方式删除它们,但 Dagger 实际上是通过反射注入(inject)/访问它们。这类似于 RoboGuice。

它还必须保留 Dagger 生成的所有适配器类。

它还必须保留与这些适配器类相关的所有类名,以便名称仍然匹配。在此示例中,这些几乎都是 coffee 包中的所有类,因此最简单的方法是使用通配符。对于其他应用程序,此行将有所不同。

最后,它还必须保留类 dagger.Lazy 的名称,因为它的名称在生成的代码中被硬编码为字符串。

关于android - Dagger 不能创建对象图,尽管它可以生成点文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18102084/

相关文章:

angular - 为什么 Angular CLI 不会自动在提供者数组中添加服务?

java - 如何阻止 ProGuard 从类中剥离可序列化接口(interface)

Android ProGuard 使用 gradle 插件 3.0.1(4.1?)构建签名的 apk 失败

Android 指纹代码在服务类中不起作用

Android - 访问 MainActivity 实例

android - 闹钟管理器在 Android 6.0 上无法在后台运行

java - 为什么 Dagger 注入(inject)不起作用但 component.getObject 可以

android - 如何在 AlertDalog 中自动将 EditText 大写?

java - Guice:在创建模块之前实例化单例

android - 将构建类型更改为 Release 会导致某些类出现 "Cannot resolve symbol"