【问题标题】:Kotlin: Dagger2 @Inject context var is always nullKotlin:Dagger2 @Inject 上下文变量始终为空
【发布时间】:2017-10-11 12:41:47
【问题描述】:

我正在尝试在未与 Android 连接的 AndroidStudio 中做模块,它没有活动,但我需要 Context 来处理诸如 Room 数据库之类的一些事情。

这是我的设置:

应用组件

@Singleton
@Component(modules = arrayOf(AndroidSupportInjectionModule::class, AppModule::class))
interface AppComponent : AndroidInjector<NexoApplication> {

@Component.Builder
interface Builder {
    @BindsInstance
    fun application(application: NexoApplication): Builder
    fun build(): AppComponent
 }

override fun inject(app: NexoApplication)
}

AppModule

@Module
class AppModule {
@Singleton @Provides
fun provideLogger(application: NexoApplication) = LogNexoManager(application)
}

AppLifecycleCallbacks

interface AppLifecycleCallbacks {
fun onCreate(application: Application)
fun onTerminate(application: Application)
}

应用

class NexoApplication: DaggerApplication() {

@Inject lateinit var appLifecycleCallbacks: AppLifecycleCallbacks

override fun applicationInjector() = DaggerAppComponent.builder()
        .application(this)
        .build()

override fun onCreate() {
    super.onCreate()
    appLifecycleCallbacks.onCreate(this)
}

override fun onTerminate() {
    appLifecycleCallbacks.onTerminate(this)
    super.onTerminate()
   }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.elstatgroup.elstat">

<application
    android:name="com.elstatgroup.elstat.NexoApplication"
    android:allowBackup="true"
    android:label="@string/app_name"
    android:supportsRtl="true">
</application>

我尝试像这样向我的主类注入上下文:

class LogNexoManager(app: Application){
   var logRepository: LogRepository


init {
    logRepository = LogRepositoryImpl(app)

 }
}

示例单元测试总是错误的

   @Test
fun proceedWithLogs(){
    val logManager = LogManager()
}

例外是:

kotlin.UninitializedPropertyAccessException:lateinit 属性应用尚未初始化

更新: 我进行了@Emanuel S 提出的更改,现在出现如下错误:

错误:任务 ':nexo:kaptDebugKotlin' 执行失败。 内部编译器错误。查看日志了解更多详情

我的 Build.gradle 文件是:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion 26

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

}

ext.daggerVersion = '2.11'
ext.roomVersion = '1.0.0-alpha9'

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

// RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.1.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

// Room
implementation "android.arch.persistence.room:runtime:$roomVersion"
implementation "android.arch.persistence.room:rxjava2:$roomVersion"
kapt "android.arch.persistence.room:compiler:$roomVersion"
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.51"


androidTestImplementation "android.arch.persistence.room:testing:$roomVersion"

compile "com.google.dagger:dagger:$daggerVersion"
compile "com.google.dagger:dagger-android:$daggerVersion"
compile "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
implementation "com.google.dagger:dagger-android-support:2.11-rc2" // version may be not up 2 date later.
}

repositories {
mavenCentral()
}

【问题讨论】:

  • 这应该修复var app : Application? = null
  • 为什么不用构造函数来声明需要的依赖呢?
  • 但是我怎样才能注入上下文来测试呢?同样的方式?

标签: android kotlin dagger-2


【解决方案1】:

这是一个简单的测试用例。未经测试,但应该展示您应该如何注入 LogManager 的概念。

@Singleton
@Component(modules = arrayOf(AndroidSupportInjectionModule::class, AppModule::class))
interface AppComponent : AndroidInjector<App> { {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: App): Builder
        fun build(): AppComponent
    }

    override fun inject(app: App)
}

@Module
class AppModule {

    @Singleton @Provides
    fun provideYourDb(application: App) = Room.databaseBuilder(application, YourDb::class.java, "your.db").build()

    @Singleton @Provides
    fun provideLogger(application: App) = LogManager(application)
}

应用程序生命周期的接口。

interface AppLifecycleCallbacks {
   fun onCreate(application: Application)
   fun onTerminate(application: Application)
}

您的应用程序应该扩展 DaggerApplication()。

class App:DaggerApplication() {

    @Inject lateinit var appLifecycleCallbacks: AppLifecycleCallbacks

    override fun applicationInjector() = DaggerAppComponent.builder()
            .application(this)
            .build()

    override fun onCreate() {
        super.onCreate()
        appLifecycleCallbacks.onCreate(this)
    }

    override fun onTerminate() {
        appLifecycleCallbacks.onTerminate(this)
        super.onTerminate()
    }

}

你终于有了一个提供的 LogManager。

class LogManager (val app: App)    

如果您真的想在 LogManager 中使用 @Inject,您可以使用 fun inject(logManager: LogManager) 在 AppComponent 中注入它。

生命周期接口用于自动注入活动/服务,以防您以后想扩展它。示例:

应用入口类

override fun onCreate() {
     super.onCreate()
     applyAutoInjector()
     appLifecycleCallbacks.onCreate(this)
}


fun Application.applyAutoInjector() = registerActivityLifecycleCallbacks(
        object : Application.ActivityLifecycleCallbacks {

            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                handleActivity(activity)
            }
         //truncated ... 
        })

注意你需要 dagger-android-support 的依赖项在你的 gradle 中拥有 AndroidSupportInjectionModule。

implementation "com.google.dagger:dagger-android-support:2.11-rc2" // version may be not up 2 date later.

【讨论】:

  • 谢谢,但现在当我尝试构建时,出现如下错误: 建议:将 'tools:replace="android:name"' 添加到 AndroidManifest.xml:24:5 的 元素-99:19 覆盖。你能帮我吗?如果可行,我会接受你的回答
  • 另外,编译器在 .application(this) 下划线并说“未解析的引用:应用程序”
  • 首先我建议您使用不同的名称,然后使用“App”。像 YourCoolApp 这样的扩展 DaggerApplication() 会很棒。其次,您需要在清单中的
  • 好的,现在在进行这些更改之后,我遇到了一个错误,例如:错误:任务':nexo:kaptDebugKotlin'的执行失败。 > 内部编译器错误。查看日志了解更多详情
  • 现在你需要仔细检查你的 gradle 日志 :-) 你快到了。调试 Dagger 并不容易,但我的示例是要走的路。
猜你喜欢
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
相关资源
最近更新 更多