Dagger2- Retrofit 没有在 ApiHelperImpl 中注入

Dagger2- Retrofit is not injecting in ApiHelperImpl

您好,我正在尝试将 retrofit 注入 ApiHelperImpl.kt class。我有以下模块和组件。

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

}

我收到一个错误

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)

为什么 retrofit 没有注入 ApiHelperImpl class。

为了在 ApiHelperImpl 中使用 @Inject,您必须将它添加到依赖关系图中(在组件上调用 inject)。在这种情况下,我会将其作为依赖项传递给 ApiHelperImpl

的构造函数
  class ApiHelperImpl @Inject constructor(val retrofit : Retrofit) : ApiHelper {

     val mRetrofit = retrofit

应该做

您可以使用模块实现相同的功能

@Module
class ApiModule {


@Provides
@Singleton
fun apiService(context: Context): WebService {
    val mBaseUrl = context.getString(if (BuildConfig.DEBUG) R.string.local_url else R.string.live_url)

    val loggingInterceptor = HttpLoggingInterceptor()
    loggingInterceptor.level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

    val okHttpClient = OkHttpClient.Builder()
            .readTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .connectTimeout(120, TimeUnit.SECONDS)
            .addInterceptor(loggingInterceptor)
            //.addNetworkInterceptor(networkInterceptor)
            .build()

    return Retrofit.Builder().baseUrl(mBaseUrl)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build().create(WebService::class.java)

}

}

也在AppComponent

中改变
@Singleton
@Component(modules = arrayOf(ApplicationModule::class, ApiModule::class))
interface AppComponent {
...

fun apiService(): WebService

...
}

您的更改

@Component(modules = arrayOf(AndroidInjectionModule::class, AppModule::class, ApiModule ::class))

在相关子模块中也添加APIModule

更新

@Component(modules = arrayOf(AndroidInjectionModule::class, AppModule::class, ActivityBuilder::class))
@Singleton
interface AppComponent {
fun inject(app: PartnerApplication)
fun apiService(): ApiHelper 
}

然后想用就注入

@Inject
var webService: WebService? = null