Я создаю приложение, которое использует Dagger для внедрения некоторых зависимостей.
Я создал несколько классов модулей, но один из них нуждается в контексте.Проблема в том, что я не знаю, как правильно представить контекст.Я перепробовал множество решений, но каждый раз получал исключение:
@Component.Builder не хватает установщиков для необходимых модулей или компонентов: [com.mamak.geobaza.di.ContextModule]
Что я должен сделать для правильного предоставления контекста?
ApiModule.kt
package com.mamak.geobaza.di
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.mamak.geobaza.utils.AppConstans.BASE_URL
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton
@Module(includes = [
RxJavaModule::class,
OkHttpModule::class
])
class ApiModule {
@Provides
@Singleton
fun gson(): Gson {
return GsonBuilder().create()
}
@Provides
@Singleton
fun gsonConverterFactory(gson: Gson): GsonConverterFactory {
return GsonConverterFactory.create(gson)
}
@Provides
@Singleton
fun retrofit(
okHttpClient: OkHttpClient,
gsonConverterFactory: GsonConverterFactory,
rxJava2CallAdapterFactory: RxJava2CallAdapterFactory
): Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BASE_URL)
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(rxJava2CallAdapterFactory)
.build()
}
}
InterfaceModule.kt
package com.mamak.geobaza.di
import android.content.Context
import com.mamak.geobaza.ui.`interface`.ProjectListItemInterfaceImpl
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
@Module(includes = [
ContextModule::class
])
class InterfaceModule {
@Provides
@Singleton
fun projectListItemInterface(context: Context): ProjectListItemInterfaceImpl {
return ProjectListItemInterfaceImpl(context)
}
}
OkHttpModule.kt
package com.mamak.geobaza.di
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@Module
class OkHttpModule {
@Provides
@Singleton
fun okHttpLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY)
}
@Provides
@Singleton
fun okHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
}
}
ProjectApiModule.kt
package com.mamak.geobaza.di
import com.mamak.geobaza.network.api.ProjectApiService
import dagger.Module
import retrofit2.Retrofit
@Module(includes = [
ApiModule::class
])
class ProjectApiModule {
fun projectApiService(retrofit: Retrofit): ProjectApiService {
return retrofit.create(ProjectApiService::class.java)
}
}
RxJavaModule.kt
package com.mamak.geobaza.di
import dagger.Module
import dagger.Provides
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import javax.inject.Singleton
@Module
class RxJavaModule {
@Provides
@Singleton
fun rxJavaCallAdapterFactory(): RxJava2CallAdapterFactory {
return RxJava2CallAdapterFactory.create()
}
}
ViewModelKey.kt
package com.mamak.geobaza.di
import androidx.lifecycle.ViewModel
import dagger.MapKey
import kotlin.reflect.KClass
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
ViewModelModule.kt
package com.mamak.geobaza.di
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.mamak.geobaza.factory.ViewModelFactory
import com.mamak.geobaza.ui.viewmodel.ProjectListViewModel
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoMap
@Module
internal abstract class ViewModelModule {
@Binds
internal abstract fun viewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(ProjectListViewModel::class)
protected abstract fun projectListViewModel(projectListViewModel: ProjectListViewModel): ViewModel
}
ContextModule.kt
package com.mamak.geobaza.di
import android.content.Context
import dagger.Module
import dagger.Provides
@Module
class ContextModule constructor(val context: Context) {
@Provides
fun context(): Context {
return context
}
}
AppComponent.kt
package com.mamak.geobaza.di
import android.app.Application
import dagger.BindsInstance
import dagger.Component
import dagger.android.support.AndroidSupportInjectionModule
import javax.inject.Singleton
@Singleton
@Component(modules = [
ApiModule::class,
ViewModelModule::class,
AndroidSupportInjectionModule::class,
InterfaceModule::class,
ContextModule::class
])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
@BindsInstance
fun apiModule(apiModule: ApiModule): Builder
@BindsInstance
fun interfaceModule(interfaceModule: InterfaceModule): Builder
@BindsInstance
fun contextModule(contextModule: ContextModule): Builder
fun build(): AppComponent
}
fun inject(appController: AppController)
}
AppController.kt
package com.mamak.geobaza.di
import android.app.Application
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class AppController : Application(), HasAndroidInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun androidInjector(): AndroidInjector<Any> {
return dispatchingAndroidInjector
}
override fun onCreate() {
super.onCreate()
DaggerAppComponent.Builder()
.application(this)
.apiModule(ApiModule())
.interfaceModule(InterfaceModule())
.contextModule(ContextModule(this))
.build()
.inject(this)
}
}