Приложение не может быть предоставлено в DomainComponent (Dagger 2) - PullRequest
0 голосов
/ 12 сентября 2018

Я реализую приложение Sampler, используя Dagger 2 для Dependency Injection.

Но я не могу использовать свои Сервисы (база данных SQLite использует Приложение), так как мое Приложение не может быть предоставлено моим AppComponent:

error: android.app.Application cannot be provided without an @Inject constructor or from an @Provides-annotated method.
    public abstract ch.ti8m.gol.daggerchaos.persistence.SqlDatabase provideSqlDatabae();
                                                                    ^
      android.app.Application is injected at
          ch.ti8m.gol.daggerchaos.domain.di.DomainModule.provideSQLDatabase(app)
      ch.ti8m.gol.daggerchaos.persistence.SqlDatabase is provided at
          ch.ti8m.gol.daggerchaos.domain.di.DomainComponent.provideSqlDatabae()

Мой AppModule

@Module
class AppModule() {

    @Provides
    @Singleton
    fun provideContext(application: Application): Context {
        return application
    }

    @Provides
    @Singleton
    fun provideApplication(app: App): Application {
        return app
    }
}

Мой AppComponent

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): AppComponent
    }

    fun inject(app: App)
}

Мой DomainModule

@Module
class DomainModule {

    @Provides
    @Singleton
    fun providePizzaService(pizzaDAO: PizzaDAO): PizzaService {
        return PizzaServiceImpl(pizzaDAO)
    }

    //TODO get Application form App Component
    @Provides
    @Singleton
    fun provideSQLDatabase(app: Application): SqlDatabase {
        return SqlDatabase(app)
    }

    @Provides
    @Singleton
    fun providePizzaDAO(db: SqlDatabase): PizzaDAO {
        return PizzaDAO(db)
    }    
}

Мой доменный компонент

@Singleton
@Component(modules = [AppModule::class, DomainModule::class])
interface DomainComponent {

    fun providePizzaService(): PizzaService
    fun provideSqlDatabae(): SqlDatabase
    fun providePizzaDAO(): PizzaDAO

    fun inject(mainActivity: MainActivity)
    fun inject(activityMainPresenterImpl: ActivityMainPresenterImpl)
}

Мое приложение

class App : Application() {

    private lateinit var domainComponent: DomainComponent

    override fun onCreate() {
        super.onCreate()

        domainComponent = DaggerDomainComponent.builder()
                .appModule(AppModule())
                .application(this)
                .domainModule(DomainModule())
                .build()

        Timber.plant(Timber.DebugTree())
    }

    fun getDomainComponent(): DomainComponent {
        return domainComponent
    }
}

Где я его впрыскиваю

class ActivityMainPresenterImpl(private val activityMainView: ActivityMainView) : ActivityMainPresenter {
    @Inject
    lateinit var pizzaService: PizzaService

    init {
        DaggerDomainComponent.builder().build().inject(this)
    }
...

Я только начал использовать Dagger 2 для Dependency Injection в Android, так что я уверен, что испортил структуру Injection.

Кто-нибудь знает, что я пропустил или не смог реализовать должным образом (я знаю, что существует множество способов реализовать DI с помощью Dagger)?

1 Ответ

0 голосов
/ 12 сентября 2018

С точки зрения ошибок кинжала, похоже, что у вашего DomainComponent отсутствует привязка для экземпляра App, который необходим для предоставления класса Application, используемого в вашем DomainModule.

Вы можете добавить Component.Builder к DomainComponent, чтобы обеспечить это, как вы сделали с вашим AppComponent *

@Singleton
@Component(modules = [AppModule::class, DomainModule::class])
interface DomainComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun app(app: App): Builder
        fun build(): DomainComponent
    }
    fun inject(mainActivity: MainActivity)
}

* Обратите внимание, что ваш AppComponent имеет неправильную привязку, поскольку он привязывает Application, а не App экземпляр. * * * * * * * * *

не был использован, возможно, он вам не нужен? *1013*

При создании DaggerDomainComponent вам потребуется предоставить экземпляр App.

DaggerDomainComponent.builder()
        .app(this) // App reference
        .build()

Кроме того, выглядит немного странно, что вы создаете DomainComponent в своем Приложении, но затем создаете новый DomainComponent, чтобы позволить докладчику вводить себя - вы, вероятно, хотите реструктурировать это, чтобы можно было использовать тот же DomainComponent для инъекций, создание нового компонента каждый раз приведет к потере части вашей области видимости.

...