当前位置: 首页 > 知识库问答 >
问题:

Kotlin lateinit无法使用@Inject注释

江航
2023-03-14

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

我有一个模块,它有几个@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)
}

//添加LoginService类

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

共有1个答案

司空修贤
2023-03-14

因为你混合了两个独立的东西:通过虚空注入(MyClass myClass)的成员注入和构造函数注入。

事实上,你甚至有一个单独的“应该是成员注入的”字段,尽管从技术上讲,你可以把它作为构造函数参数来接收。

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
) {
    ...
}

你拥有那些类,所以没有理由使用< code > @ field:Inject late init var < code > void Inject(my class my class);这里。

 类似资料:
  • 我已经在我的项目中实现了Hilt依赖项,但是当我需要构造函数的@inject注释时,它就不起作用了。基本上,当我试图手动导入它时,我发现javax中的inject文件夹是空的。因此该结构类似于javax.inject。之后,我什么也得不到,因为inject文件夹是空的。我试过重建和清洁他的项目。我也尝试过使缓存无效,但似乎没有任何效果。我怎么才能让这起作用? 依赖项列表 刀柄版本-2.37

  • 问题内容: 我试图将在Spring上下文中定义的bean注入到CDI托管组件中,但没有成功。不会注入Bean,而是在每次执行注入时都会创建一个新实例。我的环境是带有JBoss Weld的Tomcat 7。 Spring ApplicationContext很简单: CDI托管bean如下所示: 这是我的 但是,当我从JSF页面访问属性时,每次访问时都会创建一个新实例。这是一个简单的示例: 我得到以

  • 我正在尝试使用JAX-RS(泽西岛)创建一个简单的REST服务,而不使用Spring。我想要有典型的结构:资源,使用服务(典型接口与方法,查找全部...),并且该服务注入到资源中。 似乎CDI会自动扫描豆子并注入它们(在项目中有一个空),但是......它不适合我。 这是我的资源类: 这是我的服务及其impl类(这是一个模拟...): 我在这个类中使用了“无web.xml”配置: 我发现的唯一解决

  • 问题内容: 我怎样才能像注入的依赖,,,,等的?在我的特定情况下,我需要通过以下方式注入Spring托管的: 但是,它没有注入,而是保留了null,导致。似乎,并且t也不起作用。 如何在验证器中注入服务依赖项,以便可以访问数据库? 问题答案: 在不被注入容器管理。你需要使其成为托管bean。使用Spring ,CDI @Named或JSF 代替,以便使其成为托管bean,从而有资格进行依赖项注入。

  • (子资源)再次基于构造函数中传入的用户实现为普通的Jersey类。 但是,我的子资源也需要访问字段(如或)。根据Jersey文档,字段不会为子资源注入,因为它们的生命周期未知(文档似乎是真的)。 这对我来说是非常不可原谅的:我真的需要访问这些值。 作为一种解决办法,我目前将这些值作为额外的构造函数参数传递给我的子资源,我认为这一切都不舒服。 我能以某种方式创建这些映射吗? 问题是,我不知道如何在G