Реализация простого примера Dagger2 - PullRequest
0 голосов
/ 19 сентября 2019

Я новичок в использовании Dagger2 (я всегда использовал Koin) и пытаюсь реализовать простой пример, но я не знаю, чего мне не хватает.Это то, что я получил до сих пор.

app.gradle :

ext.daggerVersion = '2.23.2'

implementation "com.google.dagger:dagger:$daggerVersion"
implementation "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"

AppModule.kt :

@Module
class AppModule {
    @Provides
    @Singleton
    fun provideApplication(app: App): Application = app

    @Provides
    @Singleton
    fun provideTestOperator(testOperator: TestOperator) = testOperator

    @Provides
    @Singleton
    fun provideTestClass(testClass: TestClass) = testClass

}

AppComponent.kt :

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    AppModule::class
])
interface AppComponent : AndroidInjector<App> {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(app: App): Builder
        fun build(): AppComponent
    }
}

TestClass.kt & TestOperator.kt в том же файле:

class TestClass @Inject constructor(private val testOperator: TestOperator) {
    fun getRandomValueFromCTest(): Int = testOperator.generateRandomNumber()
}

class TestOperator @Inject constructor() {
    fun generateRandomNumber(): Int = Random.nextInt()
}

App.kt :

class App : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerAppComponent.builder().application(this@App).build()
    }
}

MainActivity.kt :

class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var testClass: TestClass

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onResume() {
        super.onResume()
        val x = testClass.getRandomValueFromCTest()
    }
}

Ошибка: testClass == null

Ответы [ 3 ]

1 голос
/ 19 сентября 2019

AppModule.kt : укажите контекст приложения.Не нужно писать @singleton @provides для ваших классов Test * (я пойму почему)

@Module
class AppModule {
    @Provides
    @Singleton
    fun provideApplication(app: App): Context = app.applicationContext
}

AppComponent.kt : @Component.Builder устарела IIRC.Используйте @Component.Factory.И замените AndroidInjectionModule::class на AndroidSupportInjectionModule::class, так как мы используем dagger-android-support и Android *Compat*.Обратитесь к новому модулю под названием ActivityModule::class.

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

    @Component.Factory
    abstract class Factory : AndroidInjector.Factory<App>
}

TestClass.kt & TestOperator.kt : поскольку вы предоставляете синглтоны, написав метод @singleton и @provides, я полагаю, выхочу, чтобы они были одиночками.Просто аннотируйте определение класса с помощью @Singleton, и кинжал позаботится об этом.Нет необходимости писать методы @Provides.

@Singleton
class TestClass @Inject constructor(private val testOperator: TestOperator) {
    fun getRandomValueFromCTest(): Int = testOperator.generateRandomNumber()
}

@Singleton
class TestOperator @Inject constructor() {
    fun generateRandomNumber(): Int = Random.nextInt()
}

App.kt : Использование фабрики вместо компоновщика, поскольку @Component.Builder устарело.

class App : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerAppComponent.factory().create(this)
    }
}

ActivityModule.kt : Предоставьте модуль кинжалу для создания ваших действий.

@Module
interface ActivityModule {

    @ContributesAndroidInjector
    fun provideMainActivity(): MainActivity
}

MainActivity.kt : Наконец,продлить с DaggerAppCompatActivity.

class MainActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var testClass: TestClass

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onResume() {
        super.onResume()
        val x = testClass.getRandomValueFromCTest()
    }
}

Я считаю, что это должно работать без проблем, потому что так выглядит моя установка.Для получения дополнительной информации вы можете ознакомиться с этим образцом и новыми более простыми документами по адресу dagger.dev / android

1 голос
/ 19 сентября 2019

Вы пропустили фактический инъекционный вызов.

class MainActivity : AppCompatActivity() {
  @Inject
  lateinit var testClass: TestClass

  override fun onCreate(savedInstanceState: Bundle?) {
      AndroidInjection.inject(this)
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)
  }
0 голосов
/ 19 сентября 2019

MainActivity должен расширяться DaggerActivity, а не AppCompatActivity

...