Dagger2 - 无法满足依赖性

时间:2018-04-22 15:44:56

标签: android kotlin dagger-2 dagger

我对SearchPresenter对象的注入有问题。我已经将依赖图修改了50多次,无法弄清问题是什么:

e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/di/AppComponent.java:8: error: [br.com.alexpfx.cervejas.di.beers.BeersComponent.inject(br.com.alexpfx.cervejas.beers.BeersFragment)] br.com.alexpfx.cervejas.search.SearchPresenter cannot be provided without an @Provides- or @Produces-annotated method.
public abstract interface AppComponent {
                ^
      br.com.alexpfx.cervejas.search.SearchPresenter is injected at
          br.com.alexpfx.cervejas.beers.BeersFragment.searchPresenter
      br.com.alexpfx.cervejas.beers.BeersFragment is injected at
          br.com.alexpfx.cervejas.di.beers.BeersComponent.inject(beersFragment)

我是这些组件和模块:

@Singleton
@Component(
        modules = [AppModule::class, ServiceModule::class]
)
interface AppComponent {
    fun inject (app: BeerApp)
    fun plus (): LoginSubComponent
    fun plus (searchModule: UntappedSearchModule): BeersComponent

}



@Module
class AppModule(val app: BeerApp) {

    @Singleton
    @Provides
    fun app(): BeerApp = app

}


@Module
class ServiceModule {
    companion object {
        private const val BASE_URL = "https://api.untappd.com/"
    }

    @Singleton
    @Provides
    fun provideUntappedConfig(): UntappdConfig {
        return UntappdConfig(BuildConfig.UNTAPPDCLIENTID, BuildConfig.UNTAPPDCLIENTSECRET)
    }


    @Singleton
    @Provides
    fun retrofit(): Retrofit {
        return Retrofit.Builder().baseUrl(BASE_URL).addCallAdapterFactory(RxJava2CallAdapterFactory
            .create()).addConverterFactory(GsonConverterFactory.create()).build()

    }

    @Singleton
    @Provides
    fun provideUntappedService(retrofit: Retrofit): UntappedService {
        return retrofit.create(UntappedService::class.java)
    }            
}


@Module
class UntappedSearchModule (private val searchView: SearchView) {

    @PerFragment
    @Provides
    fun provideSearchView () = searchView


    @PerFragment
    @Provides
    fun provideSearchInteractor (searchInteractorImpl: SearchInteractorImpl): SearchInteractor {
        return searchInteractorImpl
    }



    @PerFragment
    @Provides
    fun provideSearchPresenter (searchView: SearchView, searchInteractor: SearchInteractor) : SearchPresenter{
        return SearchPresenterImpl(searchView, searchInteractor)
    }

}

SearchPresenter取决于SearchView中提供的UntappedSearchModule

@PerFragment
@Provides
fun provideSearchView () = searchView
提供的

SearchInteractor

@PerFragment
    @Provides
    fun provideSearchInteractor (searchInteractorImpl: SearchInteractorImpl): SearchInteractor {
        return searchInteractorImpl
    }

SearchInteractorImpl已在构造函数中注释:

@PerFragment
class SearchInteractorImpl @Inject constructor(private val beerService: UntappedService,
                                               private val config: UntappdConfig) : SearchInteractor {

    override fun searchBeers(query: String): io.reactivex.Observable<List<SearchedBeerVO>> {
        return beerService.searchBeers(config.clientId, config.clientSecret, query).map({ t -> null })
    }
}

取决于来自UntappedService

UntappdConfigServiceModule
@Singleton
    @Provides
    fun provideUntappedConfig(): UntappdConfig {
        return UntappdConfig(BuildConfig.UNTAPPDCLIENTID, BuildConfig.UNTAPPDCLIENTSECRET)
    }



@Singleton
@Provides
fun provideUntappedService(retrofit: Retrofit): UntappedService {
    return retrofit.create(UntappedService::class.java)
}

Retrofit也在这个模块中。 BeersComponent和BeersFragment是:

@PerFragment
@Subcomponent(modules = [UntappedSearchModule::class])
interface BeersComponent {
    fun inject(beersFragment: BeersFragment)
}

class BeersFragment : BaseFragment(), SearchView, AnkoLogger {

    override fun injectDependencies(appComponent: AppComponent) {
        appComponent.plus(UntappedSearchModule(this)).inject(this)
    }


    @Inject
    lateinit var searchPresenter: SearchPresenter

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        return inflater.inflate(R.layout.fragment_beers, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        setupRecycler()

        searchPresenter.search("stella")
    }

    private fun setupRecycler() {

        recyclerSearchResult.layoutManager = LinearLayoutManager(context)

    }


    override fun displayResults(beers: List<SearchedBeerVO>) {
        info("beers: "+beers.size)

        recyclerSearchResult.adapter = BeersAdapter(beers)
    }


}

BaseFragment:

abstract class BaseFragment : Fragment()  {

    private val appComponent by lazy {
        (activity!!.application as BeerApp).component
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        injectDependencies(appComponent)
    }

    abstract fun injectDependencies (appComponent: AppComponent)

}

---------编辑

我将UntappedSearchModule更改为:

@Module
class UntappedSearchModule (private val searchView: SearchView) {

    @PerFragment
    @Provides
    fun provideSearchView () = searchView

    @PerFragment
    @Provides
    fun provideSearchPresenterImpl (searchView: SearchView, searchInteractor: SearchInteractor) : SearchPresenterImpl{
        return SearchPresenterImpl(searchView, searchInteractor)
    }


    @Module(includes = arrayOf(UntappedSearchModule::class))
    abstract class SearchPresenterModule {

        @Binds
        abstract fun provideSearchPresenter (searchPresenterImpl: SearchPresenterImpl):SearchPresenter
    }


    @PerFragment
    @Provides
    fun provideSearchInteractor (searchInteractorImpl: SearchInteractorImpl): SearchInteractor {
        return searchInteractorImpl
    }

}


@PerFragment
@Subcomponent(modules = [UntappedSearchModule::class, UntappedSearchModule.SearchPresenterModule::class])
interface BeersComponent {
    fun inject(beersFragment: BeersFragment)
}

但同样的问题:

e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/di/AppComponent.java:8: error: [br.com.alexpfx.cervejas.di.beers.BeersComponent.inject(br.com.alexpfx.cervejas.beers.BeersFragment)] br.com.alexpfx.cervejas.search.SearchPresenterImpl cannot be provided without an @Inject constructor or from an @Provides-annotated method.
public abstract interface AppComponent {
                ^
      br.com.alexpfx.cervejas.search.SearchPresenterImpl is injected at
          br.com.alexpfx.cervejas.di.UntappedSearchModule.SearchPresenterModule.provideSearchPresenter(searchPresenterImpl)
      br.com.alexpfx.cervejas.search.SearchPresenter is injected at
          br.com.alexpfx.cervejas.beers.BeersFragment.searchPresenter
      br.com.alexpfx.cervejas.beers.BeersFragment is injected at
          br.com.alexpfx.cervejas.di.beers.BeersComponent.inject(beersFragment)

---我简化了SearchPresenter以避免使用@Binds并删除了依赖项:

@PerFragment
class SearchPresenterImpl @Inject constructor() :
    SearchPresenter {


    override fun search(query: String) {
//        interactor.searchBeers(query).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
//            .subscribe({ beers ->
//                beers.forEach({ t: SearchedBeerVO? -> println(t) })
//            })
    }
}


interface SearchPresenter  {
    fun search (query: String)
}



@PerFragment
    @Provides
    fun provideSearchPresenterImpl (searchPresenterImpl: SearchPresenterImpl) : SearchPresenter{
        return searchPresenterImpl

    }
  • 还是同样的问题....

但如果我使用./gradlew build运行它会显示不同的错误:

> Configure project :app 
Could not find google-services.json while looking in [src/nullnull/debug, src/debug/nullnull, src/nullnull, src/debug, src/nullnullDebug]
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
Could not find google-services.json while looking in [src/nullnull/release, src/release/nullnull, src/nullnull, src/release, src/nullnullRelease]
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)

> Task :app:processDebugGoogleServices 
Parsing json file: /home/alexandre/dev/projetos/gitlab/Cervejas/app/google-services.json

e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/search/SearchInteractorImpl.java:15: error: cannot find symbol
    public io.reactivex.Observable<java.util.List<br.com.alexpfx.cervejas.common.SearchedBeerVO>> searchBeers(@org.jetbrains.annotations.NotNull()
                       ^
  symbol:   class Observable
  location: package io.reactivex
e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/network/UntappedService.java:9: error: cannot find symbol
    public abstract io.reactivex.Observable<br.com.alexpfx.cervejas.network.search.SearchResponse> searchBeers(@org.jetbrains.annotations.NotNull()
                                ^
  symbol:   class Observable
  location: package io.reactivex
e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/search/SearchInteractor.java:9: error: cannot find symbol
    public abstract io.reactivex.Observable<java.util.List<br.com.alexpfx.cervejas.common.SearchedBeerVO>> searchBeers(@org.jetbrains.annotations.NotNull()
                                ^
  symbol:   class Observable
  location: package io.reactivex
e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/login/LoginActivity.java:8: error: cannot find symbol
    private final com.google.firebase.auth.FirebaseAuth firebaseAuth = null;
                                          ^
  symbol:   class FirebaseAuth
  location: package com.google.firebase.auth
e: /home/alexandre/dev/projetos/gitlab/Cervejas/app/build/tmp/kapt3/stubs/debug/br/com/alexpfx/cervejas/login/LoginActivity.java:17: error: cannot find symbol
    public final com.google.firebase.auth.FirebaseAuth getFirebaseAuth() {
                                         ^
  symbol:   class FirebaseAuth
  location: package com.google.firebase.auth

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.
> Compilation error. See log for more details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
15 actionable tasks: 2 executed, 13 up-to-date
alexandre@alexandre-aero ~/dev/projetos/gitlab/Cervejas $ 

在Android Studio中,它不会显示这些问题。如果我删除了对Fragment的SearchPresenter依赖,它可以正常工作。

---发现了问题。

出于某种奇怪的原因,错误地使用@Qualifier实现了范围注释:

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
@Scope
annotation class PerFragment

0 个答案:

没有答案