为什么在尝试注入Conext时出现此错误?

时间:2018-07-27 21:55:03

标签: android dependency-injection dagger-2

如果有多个模块并且它们都提供应用程序上下文,那么如何将conext注入某个类(例如活动)?

这里有两个模块,都提供应用程序上下文,并且componenet具有getConext()函数和其他一些已定义的

DataModule

@Module
class DataModule(@ApplicationContext val mAppContext: Context) {

    @Singleton
    @Provides
    @ApplicationContext
    internal fun provideAppContext(): Context {
        return mAppContext
    }
    ... ...

    // provide the DataManagerAdapterImpl

    @Provides
    @Singleton
    internal fun provideDataManagerAdapter(dataManagerAdapter: DataManagerAdapterImpl): DataManagerAdapter {
        return dataManagerAdapter
    }
}

UIModule

@Module
class UIModule(@ApplicationContext private val applicationContext: Context) {

    @Singleton
    @Provides
    @ApplicationContext
    internal fun provideAppContext(): Context {
        return applicationContext
    }
    ... ...
}

组件网络:

@Singleton
@Component(modules = arrayOf(UIModule::class, DataModule::class))
interface UIComponent {

    @ApplicationContext
    fun getContext(): Context

    fun dataManagerAdapter(): DataManagerAdapter
    ... ...

    fun inject(dataManagerAdapter: DataManagerAdapter)
    fun inject(loginActivity: LoginActivity)
}

喷油器助手:

class DiInjector constructor(@ApplicationContext appContext: Context) {

    companion object {
        private val sUIComponent: UIComponent by lazy {
            DaggerUIComponent.builder()
                    .dataModule(DataModule(appContext))
                    .uIModule(UIModule(appContext))
                    .build()
        }
        ......

        getUIComponent() : UIComponent{
            return sUIComponent
        }
    }
}

该类注入上下文:

abstract class DataManagerAdapter {

    @Inject
    lateinit var context: Context
    ... ...
}

及其派生类:

class DataManagerAdapterImpl @Inject
constructor() : DataManagerAdapter() {

    init {
        DiInjector.getUIComponent().inject(this)  //<== will inject the context
    }
    ......
}

以及注入DataManagerAdapterImpl的活动

class LoginActivity : AppCompatActivity() {

    @Inject
    lateinit var mDataManagerAdapter: DataManagerAdapter

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_activity)

        // this will get the UIComponent
        DiInjector.getUIComponent().inject(this)  //<== will inject the actual DataManagerAdapterImpl
        ......
    }
    ... ...
}
  1. 如果DataModule和UIModule均提供了Context,则会出现以下错误,并且确实是Componenet的getConext()不知道从哪个模块获取DataModule或UIModule。

           e: ../di/UIComponent.java:23: error: @com.data.scope.ApplicationContext android.content.Context is bound multiple times:
    public abstract android.content.Context getContext();
    ^
    @org.jetbrains.annotations.NotNull @com.data.scope.ApplicationContext @Provides @Singleton android.content.Context com.data.di.module.UIModule.provideAppContext$sample_debug()
    @org.jetbrains.annotations.NotNull @com.data.scope.ApplicationContext @Provides @Singleton android.content.Context com.data.di.module.DataModule.provideAppContext$sample_debug()
    
  2. 如果在DataModule中注释掉上下文提供部分fun provideAppContext(): Context,那么现在只有UIModule提供上下文。但这将导致追溯到getContext()部分的错误。

不确定为什么componenet的getContext()无法提供UIModule中的上下文,e: ../di/component/UIComponent.java:35: error: android.content.Context cannot be provided without an @Provides-annotated method. public abstract com.data.DataManagerAdapter DataManagerAdapter(); ^ android.content.Context is injected at com.data.DataManagerAdapter.context data.DataManagerAdapterImpl is injected at com.di.module.DataModule.provideDataManagerAdapter$doubleplay_debug (DataManagerAdapter) com.data.DataManagerAdapter is provided at com.di.component.UIComponent.DataManagerAdapter() e: ../di/UIComponent.java:40: error: android.content.Context cannot be provided without an @Provides- or @Produces-annotated method. public abstract void inject(@org.jetbrains.annotations.NotNull() ^ android.content.Context is injected at com.data.DataManagerAdapter.context com.data.DataManagerAdapter is injected at com.di.component.UIComponent.inject(DataManagerAdapter) e: ../di/UIComponent.java:43: error: android.content.Context cannot be provided without an @Provides-annotated method. public abstract void inject(@org.jetbrains.annotations.NotNull() ^ android.content.Context is injected at com.data.DataManagerAdapter.context data.DataManagerAdapterImpl is injected at com.di.module.DataModule.provideDataManagerAdapter$doubleplay_debug(DataManagerAdapter) com.data.DataManagerAdapter is injected at com.data.LoginActivity.mAccountManagerAdapter com.data.LoginActivity is injected at com.di.component.UIComponent.inject(LoginActivity) 现在是单个提供:

DiInjector.getUIComponent().inject(this)

===

更新

在标记建议的情况下(将上下文作为构造函数放入参数中,并在DataManagerAdapter::init{} block)中删除对abstract class DataManagerAdapter(var context: Context) { // put in constructor //@Inject //lateinit var context: Context ... ... } 的调用,它仍然不起作用。

class DataManagerAdapterImpl @Inject
constructor(context: Context) : DataManagerAdapter(context) {

init {
// remove it, now context is in constructor's param
//DiInjector.getUIComponent().inject(this)  //<== will inject the context
}
......
}

子类

e: ../di/UIComponent.java:43: error: android.content.Context cannot be 
provided without an @Provides-annotated method.
public abstract void inject(@org.jetbrains.annotations.NotNull()
^
android.content.Context is injected at
com. data.DataManagerAdapterImpl.<init>(context)
    com.data.DataManagerAdapterImpl is injected at

com.di.module.DataModule.
     provideDataManagerAdapter$doubleplay_debug(DataManagerAdapter)
com.data.DataManagerAdapter is injected at
com.data.LoginActivity.mAccountManagerAdapter
com.data.LoginActivity is injected at
com.di.component.UIComponent.inject(LoginActivity)

在无法解析压缩文件时仍然出现错误

generic base class DataManagerAdapter

以下理解是否正确?

LoginActivity依赖于fun inject(loginActivity: LoginActivity),而UIComponent的generic base class DataManagerAdapter可以解决该问题。

fun provideDataManagerAdapter(dataManagerAdapter: DataManagerAdapterImpl): DataManagerAdapter { return dataManagerAdapter }, 由DataModule的

提供
sub class DataManagerAdapterImpl

依赖于实现sub class DataManagerAdapterImpl

DataManagerAdapter(var context: Context)的实现使用构造函数注入,因此它是隐式提供的。

现在,class DataManagerAdapterImpl @Inject constructor(context: Context) : DataManagerAdapter(context) {} 和子类中的上下文是必需的参数

fun provideAppContext(): Context

因此它依赖于UIComponenet通过UIModule的"android.content.Context cannot be provided without an @Provides-annotated method"提供的上下文。

为什么它仍然抱怨{{1}}?

0 个答案:

没有答案
相关问题