Kotlin lateinit 不使用@Inject 注释

标签 kotlin dagger-2

我是 dagger 2 和 kotlin 的新手。获取未初始化的 lateinit 属性。

我有一个模块,它有几个 @Provides 方法,但其中一个类无法创建使用 @Inject 和 lateinit 的对象。

登录服务采用"LoginAPI" 作为参数并且工作正常,但因为我希望所有与登录相关的 API 使用相同的服务。还有一个与 API 相关的“LoginWithOrgAPI”

现在我的需要是在 LoginService 类中需要时获取任何 API 对象。所以我尝试将 lateinit 与 @Inject 一起使用,如 LoginService 类中所示,但它不起作用。

@Module(includes = [(NetworkingModule::class)])

class LoginModule {

    @Provides
    fun provideLoginApi(retrofit: Retrofit): LoginApi =
            retrofit.create(LoginApi::class.java)

    @Provides
    fun provideLoginWithOrgApi(retrofit: Retrofit): LoginWithOrgApi =
            retrofit.create(LoginWithOrgApi::class.java)

    @Provides
    fun provideLoginService(api: LoginApi): LoginService =
            LoginService(api)

    @Provides
    fun provideLoginInteractor(apiService: LoginService): LoginInteractor =
            LoginInteractor(apiService)
}

//添加登录服务类

class LoginService(val loginAPI: LoginApi) {

    @Inject
    lateinit var loginWithOrgApi: LoginWithOrgApi


    fun loginAPIService(user: String, password: String?, extension: String, otp: String?,
                       hardwareId: String): Single<LoginAPIResponseData> {
        password?.let {

            return loginAPI.getLogin(user, it, extension, null, hardwareId)
        }?: run {
            return loginAPI.getLogin(user, null, extension, otp, hardwareId)
        }
    }

    fun loginWithOrg(user: String, password: String?, extension: String, otp: String?,
                     userId: String, hardwareId: String): Single<LoginAPIResponseData>{
        password?.let {

            return loginWithOrgApi.getLogin(user, it, extension, null, userId, hardwareId)
        }?: run {
            return loginWithOrgApi.getLogin(user, null, extension, otp, userId, hardwareId)
        }
    }
}

//组件

@Component(modules = [(LoginModule::class)])

    interface LoginComponent {

           fun loginInteractor(): LoginInteractor

    }

//接口(interface)接口(interface)

interface LoginWithOrgApi {

    @POST("access/v1/login/")
      @FormUrlEncoded
      fun getLogin(@Field("user") user: String,
                   @Field("password") password: String?,
                   @Field("mobile_extension") extension: String,
                   @Field("otp") otp: String?,
                   @Field("user_id") userId: String,
                   @Field("hardware_id") hardwareId: String): Single<LoginAPIResponseData>

}

在尝试调用方法“loginWithOrg”时出现崩溃提示 “lateinit” 属性未初始化

我的理解是,一旦通过模块定义和提供,我就可以通过依赖图中的@Inject 获取对象,但这里缺少一些东西。

//LoginService 类的目标

class LoginService() {

    @Inject
    var loginWithOrgApi: LoginWithOrgApi 


@Inject
        var loginApi: LoginApi



    fun loginAPIService(user: String, password: String?, extension: String, otp: String?,
                       hardwareId: String): Single<LoginAPIResponseData> {
        password?.let {

            return loginAPI.getLogin(user, it, extension, null, hardwareId)
        }?: run {
            return loginAPI.getLogin(user, null, extension, otp, hardwareId)
        }
    }

    fun loginWithOrg(user: String, password: String?, extension: String, otp: String?,
                     userId: String, hardwareId: String): Single<LoginAPIResponseData>{
        password?.let {

            return loginWithOrgApi.getLogin(user, it, extension, null, userId, hardwareId)
        }?: run {
            return loginWithOrgApi.getLogin(user, null, extension, otp, userId, hardwareId)
        }
    }
}

最佳答案

因为您混合了两个独立的东西:通过 void inject(MyClass myClass); 进行的成员注入(inject)和构造函数注入(inject)。

事实上,您甚至有一个“应该被成员注入(inject)”的单独字段,即使您在技术上可以将其作为构造函数参数接收?

class LoginService(val loginAPI: LoginApi) { // <-- constructor param + field

    @Inject
    lateinit var loginWithOrgApi: LoginWithOrgApi // <-- why is this a lateinit member injected field? 
    // this could also be constructor param

所以应该是这样的

@Module(includes = [(NetworkingModule::class)])

class LoginModule {

    @Provides
    fun loginApi(retrofit: Retrofit): LoginApi =
            retrofit.create(LoginApi::class.java)

    @Provides
    fun loginWithOrgApi(retrofit: Retrofit): LoginWithOrgApi =
            retrofit.create(LoginWithOrgApi::class.java)

    //@Provides
    //fun provideLoginService(api: LoginApi): LoginService =
    //        LoginService(api)

    //@Provides
    //fun provideLoginInteractor(apiService: LoginService): LoginInteractor =
    //        LoginInteractor(apiService)
}

class LoginService @Inject constructor(
    val loginAPI: LoginApi, 
    val loginWithOrgApi: LoginWithOrgApi
) {
    fun loginAPIService(user: String, password: String?, extension: String, otp: String?,
                       hardwareId: String): Single<LoginAPIResponseData> {
        password?.let { password ->
            return loginAPI.getLogin(user, password, extension, null, hardwareId)
        }?: run {
            return loginAPI.getLogin(user, null, extension, otp, hardwareId)
        }
    }

    fun loginWithOrg(user: String, password: String?, extension: String, otp: String?,
                     userId: String, hardwareId: String): Single<LoginAPIResponseData>{
        password?.let { password ->
            return loginWithOrgApi.getLogin(user, password, extension, null, userId, hardwareId)
        }?: run {
            return loginWithOrgApi.getLogin(user, null, extension, otp, userId, hardwareId)
        }
    }
}

class LoginInteractor @Inject constructor(
    val apiService: LoginService
) {
    ...
}

您拥有这些类,因此没有理由在此处使用 @field:Inject lateinit var + void inject(MyClass myClass);

关于Kotlin lateinit 不使用@Inject 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54288418/

相关文章:

列表回调参数上的 Kotlin 通配符捕获

Dagger 2 子组件与组件依赖关系

android - 如何在Android项目中从头开始设置DAGGER依赖注入(inject)?

android - Android apk 中的 kotlin/文件夹的用途是什么?

java - dagger2 注入(inject)的无作用域对象的生命周期是多少?

java - 从维护的角度来看,实现属性注入(inject)与构造函数注入(inject)是否更优化?

java - Dagger 2 不会注入(inject)我的对象,但可以从组件中获取

android - 如何单击 fragment 中的按钮以切换到 Kotlin 中的其他选项卡?

android - 如何在 AndroidX 中更改 Android SearchView 的 textcolor 或 queryhint textcolor?

android - Kotlin Coroutines 在 Android 中的使用