Hi I am trying to inject retrofit
in ApiHelperImpl.kt
class. I have below module and component.
AppComponent.kt
@Component(modules = arrayOf(AndroidInjectionModule::class, AppModule::class, ActivityBuilder::class))
@Singleton
interface AppComponent {
fun inject(app: PartnerApplication)
}
AppModule.kt
@Module
class AppModule {
@Provides
@Singleton
fun providesPartnerApplication(application: Application): Application = application
@Provides
@Singleton
fun providesSharedPreferences(application: Application): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(application)
}
@Provides
@Singleton
fun provideOkHttpCache(application: Application): Cache {
val cacheSize = 10 * 1024 * 1024L // 10 MiB
return Cache(application.cacheDir, cacheSize)
}
@Provides
@Singleton
fun provideMoshi(): Moshi = Moshi.Builder().build()
@Provides
@Singleton
fun provideOkHttpClient(cache: Cache): OkHttpClient {
val okHttpClient = OkHttpClient()
okHttpClient.newBuilder()
.cache(cache)
.build()
return okHttpClient
}
@Provides
@Singleton
fun provideRetrofit(moshi: Moshi, okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.build()
}
}
PartnerApplication.kt
class PartnerApplication : Application(), AnkoLogger, HasActivityInjector {
@Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> {
return activityInjector
}
override fun onCreate() {
super.onCreate()
DaggerAppComponent.create().inject(this)
}
override protected fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
ApiHelper.kt
interface ApiHelper {
fun doServerLoginApiCall(email: String, password: String): Observable<LoginResponse>
fun doServerRegistrationApiCall(): Observable<RegistrationResponse>
}
ApiHelperImpl.kt
class ApiHelperImpl : ApiHelper {
@Inject
lateinit var retrofit: Retrofit
override fun doServerLoginApiCall(email: String, password: String): Observable<LoginResponse> {
return retrofit.create(RestApi::class.java).login(email, password)
}
override fun doServerRegistrationApiCall(): Observable<RegistrationResponse> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
LoginActivity.kt
class LoginActivity : BaseActivity() {
@Inject
lateinit var loginViewModel: LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
performDependencyInjection()
super.onCreate(savedInstanceState)
val activityLoginBinding: ActivityLoginBinding = DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout.activity_login)
activityLoginBinding.loginViewModel = loginViewModel
}
}
LoginViewModel.kt
class LoginViewModel : ViewModel(), AnkoLogger {
val emailField = ObservableField<String>()
private val email: String
get() = emailField.get()
val passwordField = ObservableField<String>()
private val password: String
get() = passwordField.get()
val progressVisibility: ObservableInt = ObservableInt(View.GONE)
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
fun login(view: View) {
if (isEmailAndPasswordValid(email, password))
ApiHelperImpl().doServerLoginApiCall(email, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : CallbackWrapper<LoginResponse>() {
override fun onSuccess(loginResponse: LoginResponse) {
}
})
}
/**
* Validate email and password. It checks email and password is empty or not
* and validate email address is correct or not
* @param email email address for login
* @param password password for login
* @return true if email and password pass all conditions else false
*/
private fun isEmailAndPasswordValid(email: String, password: String): Boolean {
if (email.isEmpty()) return false
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) return false
if (password.isEmpty()) return false
return true
}
}
LoginActivityModule.kt
@Module
class LoginActivityModule {
@Provides
fun providesLoginActivityViewModel(): LoginViewModel {
return LoginViewModel()
}
}
ActivityBuilder.kt
@Module
abstract class ActivityBuilder {
@ContributesAndroidInjector(modules = arrayOf(LoginActivityModule::class))
abstract fun bindLoginActivity(): LoginActivity
}
I am getting an error
Process: com.partner.android, PID: 9697
kotlin.UninitializedPropertyAccessException: lateinit property retrofit has not been initialized
at com.partner.android.data.remote.ApiHelperImpl.doServerLoginApiCall(ApiHelperImpl.kt:32)
at com.partner.android.login.LoginViewModel.login(LoginViewModel.kt:45)
at com.partner.android.databinding.ActivityLoginBinding$OnClickListenerImpl.onClick(ActivityLoginBinding.java:298)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Why retrofit
is not injecting in ApiHelperImpl class.