本文介绍了Kotlin lateinit无法与@Inject注释一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是匕首2和科特林的新手.获取lateinit属性未初始化.

I am new to dagger 2 and kotlin both. Getting lateinit property not initialized.

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

I have a module which have few @Provides methods but one of the class not able to create object which used @Inject and lateinit.

登录服务将"LoginAPI" 作为参数,可以正常工作,但是由于我希望所有与登录相关的API都使用相同的服务.还有一个与API相关的"LoginWithOrgAPI" .

Login service takes "LoginAPI" as parameter and works fine but as i want all my login related API's to use the same service. There is one more API related "LoginWithOrgAPI".

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

Now my need is to get any API object when needed in the LoginService class. So i tries using lateinit with @Inject as show in LoginService class but its not working.

@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)
}

//添加LoginService类

// adding LoginService class

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

    }

//api接口

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" 属性未初始化

Getting the crash saying "lateinit" property not initialized when trying to call method "loginWithOrg"

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

My understanding is that once define and provided through module, i can get the object through @Inject in the dependency graph but something is missing here.

//我的LoginService类目标

// my objective for LoginService class

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);进行成员注入和构造函数注入.

Because you are mixing two independent things: member injection via void inject(MyClass myClass); and constructor injection.

实际上,即使您可以从技术上将其作为构造函数参数接收,您甚至还有一个应被成员注入"的单独字段?

In fact, you even have a separate field that "ought to be member-injected", even though you could technically receive that as a constructor param?

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


因此应如下所示.


So it should be as follows.

@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);.

You own those classes, so there is no reason to use @field:Inject lateinit var + void inject(MyClass myClass); here.

这篇关于Kotlin lateinit无法与@Inject注释一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 17:06