ApiModule.kt
@Module
class ApiModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideUserApi(retrofit: Retrofit): HeroesApi {
return retrofit.create(HeroesApi::class.java)
}
@Provides
@Singleton
fun provideApiManager(): ApiManager {
return ApiManager()
}
}
ApiManager.kt
class ApiManager {
@Inject
lateinit var mRetrofit: Retrofit
fun getAllHeroes(): MutableLiveData<Result<List<Hero>>> {
val mHeroesApi = mRetrofit.create(HeroesApi::class.java)
return NetworkHandler<List<Hero>>().makeCall(mHeroesApi.getAllHeroes())
}
}
HeroesApi.kt
interface HeroesApi {
@GET("/marvel")
fun getAllHeroes(): Call<List<Hero>>
}
Error i am getting
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property mRetrofit has not been initialized
at com.hardik.repository.network.ApiManager.getAllHeroes(ApiManager.kt:17)
at com.hardik.repository.Repository.getHeroesFromNetwork(Repository.kt:16)
at com.hardik.androidtemplate.usecase.GetHeroesUseCase.execute(GetHeroesUseCase.kt:14)
at com.hardik.androidtemplate.viewmodel.HeroListViewModel.<init>(HeroListViewModel.kt:9)
Let me know for more details
You don't need to inject Retrofit
instance in your ApiManager
. You already have Provide
method for HeroesApi
in your ApiModule
so you can directly pass it. First change your ApiManager with:
class ApiManager(private val mHeroesApi: HeroesApi) {
fun getAllHeroes(): MutableLiveData<Result<List<Hero>>> {
return NetworkHandler<List<Hero>>().makeCall(mHeroesApi.getAllHeroes())
}
}
Then change your ApiModule
@Module
class ApiModule {
// Rest code same as it is already
@Provides
@Singleton
// Since you already have Provide method which provides HerosApi,
// Dagger will automatically inject this below.
fun provideApiManager(herosApi: HerosApi): ApiManager {
return ApiManager(herosApi)
}
}
OR
You can simply change your ApiManager
to have HorseApi
injected into constructor and you won't need to have Provide
method for ApiManager
even. For this, change ApiManager with following:
// Notice the @Inject before constructor
class ApiManager @Inject constructor(private val mHeroesApi: HeroesApi) {
fun getAllHeroes(): MutableLiveData<Result<List<Hero>>> {
return NetworkHandler<List<Hero>>().makeCall(mHeroesApi.getAllHeroes())
}
}
and then, you can remove Provide
method for ApiManager
from ApiModule
because your ApiManager
only needs HerosApi
in constructor and you have defined Provide
method which returns HerosApi
so dagger already knows how to construct your ApiManager
.
So your ApiModule will finally look like this:
@Module
class ApiModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideUserApi(retrofit: Retrofit): HeroesApi {
return retrofit.create(HeroesApi::class.java)
}
// There's no need for providing ApiManager.
}