Reputation: 1148
I've started using Dagger 2 with Android Injector and faced an issue
I have 5 modules, that are composed into one component
@Singleton
@Component(modules = [AndroidInjectionModule::class,
ActivityBuilder::class,
AndroidSupportInjectionModule::class
, ApplicationModule::class,NetworkModule::class])
interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(app: DeliveryApplication)
fun service(): DeliveryApi
}
Network Module look like
@Module
class NetworkModule {
@Singleton
@Provides
fun providesDeliveryApi(retrofit: Retrofit):DeliveryApi = retrofit.create(DeliveryApi::class.java)
@Singleton
@Provides
fun providesRetrofit(okHttpClient: OkHttpClient):Retrofit =
Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
@Singleton
@Provides
fun providesOkHttpClient(context:Context): OkHttpClient {
/* val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}*/
val cacheSize = (5 * 1024 * 1024).toLong()
val myCache = Cache(context.cacheDir, cacheSize)
val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context)!!)
// setting 5 Mb Cabacity
request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
chain.proceed(request)
}
.build()
return okHttpClient
}
@Singleton
@Provides
fun provideImageLoader(context: Context) : ImageLoader {
return PicassoImageLoader(Picasso.with(context))
}
application Module look like
const val SCHEDULER_MAIN_THREAD = "mainThread"
const val SCHEDULER_IO = "io"
@Module
class ApplicationModule {
@Provides
@Named(SCHEDULER_MAIN_THREAD)
fun provideAndroidMainThreadScheduler() : Scheduler = AndroidSchedulers.mainThread()
@Provides
@Named(SCHEDULER_IO)
fun provideIoScheduler() : Scheduler = Schedulers.io()
@Provides
@Singleton
fun provideContext(application: Application): Context {
return application
}
}
ActivityBuilder is pretty simple: just combination of modules for Activities and FragmentsModule for fragments
@Module
abstract class ActivityBuilder {
@PerActivity
@ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesModule::class])
abstract fun bindMainActivity(): DeliveriesActivity
@PerActivity
@ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesDetailsModule::class])
abstract fun bindDeliveryDetailsActivity(): DeliveryDetailsActivity
}
@Module
abstract class FragmentsModule {
@ContributesAndroidInjector
abstract fun provideDeliveriesListFragment(): DeliveriesListFragment
@ContributesAndroidInjector
abstract fun provideDeliveryDetailsFragment(): DeliveryDetailsFragment
}
Delivery Module which used to provide all instances of the DeliveryActivity
@Module
class DeliveriesModule {
@Provides
@PerActivity
fun providesDeliveryRepository(deliveryApi: DeliveryApi): DeliveryRepository {
return DeliveryDownloader(deliveryApi)
}
@Provides
@PerActivity
fun providesDeliveryListUseCases(deliveryRepository: DeliveryRepository): DeliveryListUseCase {
return DeliveryListInteractor(deliveryRepository)
}
@Provides
@PerActivity
fun provideDeliveriesListFragment(): DeliveriesListFragment {
return DeliveriesListFragment()
}
}
ViewModelFactory where the problem here, the compiler says that DeliveryListUseCase cannot be provided without an @Provides-annotated method
class ViewModelFactory @Inject constructor(private val application: Application,
@Named(SCHEDULER_IO) val subscribeOnScheduler: Scheduler,
@Named(SCHEDULER_MAIN_THREAD) val observeOnScheduler: Scheduler,
private val deliveryListUseCase: DeliveryListUseCase) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return when {
modelClass.isAssignableFrom(DeliveryListViewModel::class.java) ->
DeliveryListViewModel(application,deliveryListUseCase,subscribeOnScheduler,observeOnScheduler) as T
else -> BaseViewModel(application) as T
}
}
}
Upvotes: 0
Views: 310
Reputation: 1148
Seems like I've figured out what was wrong
the problem. the DeliveriesModule which is a module of DeliveriesActivity so i have to make another Module for DeliveriesListFragment and provide the DeliveryListUseCase
Thank you, @Blackbelt, for giving me a hint
Upvotes: 0