【问题标题】:Dagger 2 Generic Type class inject errorDagger 2 Generic Type 类注入错误
【发布时间】:2021-10-22 00:11:09
【问题描述】:

由于其通用性质,我无法让MyClass 在此处被注入。

Dagger 报错:

Error:(187, 10) error: com.test.MyClass 有类型参数,不能成员注入原始类型。通过: com.test.MyComponent.inject(com.test.MyClass obj) 【类型的组件注入方式:com.test.MyClass】

我用谷歌搜索了一下,但无法找到这种情况的解决方案。

class MyClass<Type> {
    @Inject
    UserCredentials userCredentials;

    ResultProducer<Type> mRP;

    public MyClass(ResultProducer<Type> resultProd) {
        mRP = resultProd;
        Injector.getComponent().inject(this);
    }

    public Type getResult() {
        if (userCredentials.isLoggedIn()) {
            mRP.get();
        } else {
            mRP.getAnonymousCache();
        }
    }
}

@Component(modules = CredentialsModule.class )
interface MyComponent {
    void inject(MyClass obj);
}

@Module
class CredentialsModule {
    @Provides
    public UserCredentials provideUserCredentials() {
        return new UserCredentials();
    }
}

【问题讨论】:

    标签: generics dependency-injection dagger


    【解决方案1】:

    我也遇到了同样的问题,发现this article

    简而言之,您有以下选择:

    1. 不要使包含注入字段的通用包装类,使其成为您的类的一个字段并注入它而不是通用类本身。
    2. 注入子非泛型类而不是基类。所有带有 @Inject 注释的基类字段也将被注入,但它们必须是公共/受保护的,这是不好的。
    3. 在基类和私有字段中使用@Inject setter 进行注释。注入子非泛型类将导致使用从对象图中获取的参数触发设置器。

    【讨论】:

    • 所以要注意抽象类、接口和类型参数()!
    【解决方案2】:

    对于许多人来说,知道它是允许将字段注入泛型类而不注入类本身是有用的。
    在注入子类时会为您注入它。
    所以你可以:

    abstract class MyClass<? extends Something> {
        @Inject UserCredentials userCredentials;
        // you can use it further
    }
    
    class AnotherClass extends MyClass<Whatever> {
        // just inject this one
    }
    

    【讨论】:

    • 绝妙的答案!就这么简单!
    【解决方案3】:

    你可以在没有“注入”的情况下使用 dagger2。

    为你的组件添加方法:

    @Component(modules = CredentialsModule.class )
    interface MyComponent {
    void inject(MyClass obj);
    
    UserCredentials getUserCredentials();
    }
    

    并且毫无问题地使用它:

    userCredentials=Injector.getComponent().getUserCredentials();
    

    但是如果你有很多字段要注入,这种方法可能会很不方便

    【讨论】:

      【解决方案4】:

      我解决了这个问题有点不同,就像这样(我们还有 5 年,所以它在 Kotlin 中,但我猜 Java 也可以):

      // The class I want to inject, multiple generics
      class SomeDataStorage<K, V> {
      
        @Inject
        lateinit var theDependencyINeed: TheDependencyINeed
      
        init {
          ComponentSingleton.getSomeComponent().inject(this as SomeDataStorage<Any, Any>)
        }
      
        fun getValue(key: K): V {
          return theDependencyINeed.doSomeStuff() as V
        }
      }
      
      // Component
      interface MyComponent {
        fun inject(someDataStorage: SomeDataStorage<Any, Any>)
      }
      

      诀窍是获取您允许的泛型的一些共同父级(在我的情况下,我不在乎,所以我只做 Any,这就是一切)并使用它。需要一些未经检查的强制转换,但没关系。

      【讨论】:

        【解决方案5】:

        您可以使用下一种方法:

        1. 在 MainComponent.java 中声明 get* 方法
        public interface MainComponent extends AndroidInjector<MainApplication> {
            
            @NonNull
            YourAwesomeClass getYourAwesomeClass();
        }
        
        1. 在 MainApplication.java 中保存 MainComponent 实例的链接
        public class MainApplication extends AxisApplication {
            public static MainComponent mainComponent;
        
            @Override
            protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
                mainComponent = DaggerMainComponent
                        .builder()
                        .build();
                mainComponent.inject(this);
        
                return mainComponent;
            }
        
        1. 在应用中任何需要的地方注入您的课程:
        MyAwesomeClass myAwesomeClass = MainApplication.mainComponent.getYouAwesomeClass()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-08
          • 2016-11-21
          • 1970-01-01
          • 2022-09-30
          • 2023-04-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多