2017-10-11 21 views
0

Android와 연결되지 않은 AndroidStudio에서 모듈을 만들려고하는데 아무런 활동이 없지만 방 데이터베이스와 같은 여러 가지 컨텍스트가 필요합니다. 여기 Kotlin : Dagger2 @Inject context var is always null

내 설정이다 :

AppComponent

@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 property app has not been initialized

UPDATE : 내가 @Emanuel S에 의해 제안 된 변경 한 지금은 오류 등이있다 :

Error:Execution failed for task ':nexo:kaptDebugKotlin'. Internal compiler error. See log for more details

내 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() 
} 
+0

이렇게하면 'var app : Application? = null' –

+0

필수 종속성을 선언하는 데 생성자를 사용하지 않는 이유는 무엇입니까? –

+0

하지만 어떻게 테스트 컨텍스트를 주입 할 수 있습니까? 같은 방법으로? – Konrad

답변

2

다음은 간단한 테스트 케이스이다. 테스트되지는 않았지만 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) 
} 

Apps 수명주기를위한 인터페이스입니다.

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 ... 
     }) 

당신이 AndroidSupportInjectionModule을 위해 Gradle을에 단검 - 안드로이드 지원에 대한 종속성을 필요로주의하십시오.

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

고마워,하지만 지금 내가 같은 오류가 발생하려고 : 제안 : '도구 : replace = "android : name"'을 요소에 AndroidManifest.xml : 24 : 5-99 : 19에 추가하면 무시됩니다. 도울 수 있니? – Konrad

+0

또한 대답은 .application (this) 밑줄을 긋고 "unresolved reference : application"이라고 말합니다. – Konrad

+0

먼저 "App"이라는 다른 이름을 사용하는 것이 좋습니다. YourCoolApp와 같은 뭔가가 DaggerApplication()을 확장하여 멋지게 만듭니다. 둘째로 android : name = ". com.yourpackage.YourCoolApp"와 같은 매니페스트에서