Ошибка при использовании Dagger 2 с Kotlin в Android Studio - PullRequest
0 голосов
/ 10 октября 2019

Я новичок в Dagger 2, и я пытаюсь изучить его с Kotlin. Позвольте мне сначала объяснить структуру моего проекта. У меня есть имя класса "Info":

class Info constructor(var message: String) {}

Я создал модуль для этого класса "InfoModule"

    @Module
    class InfoModule {

        @Provides @Choose("HELLO")
        fun sayHello(): Info{
            return Info(message = "Hello dagger 2")
        }

        @Provides @Choose("HI")
        fun sayHi(): Info{
            return Info(message = "Hi dagger 2")
        }
}

Я создал компонентный интерфейс для этого модуля с именем "MagicBox "

  @Component(modules = [InfoModule::class])
interface MagicBox {
    fun poke(app: MainActivity)
}

Затем в MainActivity я ввел два поля для" Info "

 class MainActivity : AppCompatActivity() {



    var textView: TextView? = null;

    @Inject @field:Choose("HELLO") lateinit var infoHello: Info
    @Inject @field:Choose("HI") lateinit var infoHi: Info


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


        DaggerMagicBox.create().poke(this)

        textView = findViewById<TextView>(R.id.textView)
        textView!!.text = infoHi.message

    }
}

@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)

Как вы видите выше, я создал аннотацию @Choose, чтобы узнать, как @Qualifierработает. До сих пор код работает отлично, и это действительно магия Dagger :).

ПРОБЛЕМА НАЧИНАЕТСЯ ЗДЕСЬ: >> Затем я решил ввести в поле MainActivity еще одно поле с именем «car» таким же образом, как поле «info» вводится в MainActivity. Для этого сначала нужен класс автомобиля.

    class Car constructor(var engine: Engine, var wheels: Wheels) {

fun drive(){
    Log.d("Car","Driving")
}
}

Теперь классу автомобиля нужны двигатель и колеса. Ниже приведены классы двигателя и колеса

Класс двигателя:

class Engine  {
}

Класс колеса:

    class Wheels  {
}

Затем я создал модуль для класса автомобиля

 @Module
class CarModule {

@Provides
fun provideEngine(): Engine{
   return Engine()
}

@Provides
fun provideWheel(): Wheels{
    return Wheels()
}

@Provides @Choose("NewCar")
fun provideCar(engine: Engine, wheels: Wheels): Car{
    Log.d("NewCar", "Created")
    return Car(engine, wheels)
}

}

Компонент для Car ниже

 @Component (modules = [CarModule::class])
interface CarComponent {

    fun injectCar(mainActivity: MainActivity)


}

Затем я ввел поле car в MainActivity и попытался вызвать метод "drive" класса Car. Теперь моя MainActivity выглядит следующим образом.

    class MainActivity : AppCompatActivity() {



    var textView: TextView? = null;


    @Inject @field:Choose("HELLO") lateinit var infoHello: Info
    @Inject @field:Choose("HI") lateinit var infoHi: Info

    @Inject @field:Choose("NewCar") lateinit var  car: Car

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


        DaggerMagicBox.create().poke(this)
        textView = findViewById<TextView>(R.id.textView)
        textView!!.text = infoHi.message


        DaggerCarComponent.create().injectCar(this)
        car.drive()


    }
}

@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)

Ошибка Logcat после MakeProject:

    error: [Dagger/MissingBinding] @de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info cannot be provided without an @Provides-annotated method.
public abstract interface CarComponent {
                ^
      @de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info is injected at
          de.test.testtheapp.MainActivity.infoHello
      de.test.testtheapp.MainActivity is injected at
          de.test.testtheapp.Components.CarComponent.injectCar(de.test.testtheapp.MainActivity)

Что я действительно нахожу странным, так это то, что хотя инъекция поля «информация» раньше работала идеально,почему после добавления инжекции в поле автомобиля в logcat теперь отображается ошибка, связанная с внедрением информационного поля или класса Info. Я знаю, что это также говорит кое-что о "CarComponent". Сейчас ничего не работает. Даже «DaggerMagicBox» не решен. Я ничего не понимаю об ошибке, и я застрял на этом с двух дней. Мои знания о кинжале очень ограничены, поэтому я не знаю, что это за решение. Я буду очень благодарен, если кто-нибудь даст мне подсказку. Я использую Android Studio 3.5.1 и Dagger версии 2.21

1 Ответ

1 голос
/ 10 октября 2019

Вы пытаетесь использовать CarComponent для внедрения зависимостей MainActivity:

DaggerCarComponent.create().injectCar(this)

Но ваш CarComponent не может предоставить Info:

@Inject @field:Choose("HELLO") lateinit var infoHello: Info

Поскольку метод провайдера определен в InfoModule, а CarComponent не имеет его в списке модулей.


Вы используете два компонента для внедрения зависимостей MainActivity:

DaggerMagicBox.create().poke(this)
...
DaggerCarComponent.create().injectCar(this)

Вы должны использовать только один.

Либо добавьте CarModule в список модулей MagicBox и удалите DaggerCarComponent.create().injectCar(this).

Илидобавьте InfoModule в список модулей CarComponent и удалите DaggerMagicBox.create().poke(this)

...