Kotlin lateinit не работает с аннотацией @Inject - PullRequest
0 голосов
/ 21 января 2019

Я новичок в кинжале 2 и в котлин. Получение свойства lateinit не инициализировано.

У меня есть модуль, который имеет несколько методов @Provides, но один из классов не может создать объект, который использовал @Inject и lateinit.

Служба входа в систему принимает "LoginAPI" в качестве параметра и работает нормально, но, поскольку я хочу, чтобы все мои API, связанные с входом в систему, использовали один и тот же сервис. Есть еще один API, связанный "LoginWithOrgAPI" .

Теперь мне нужно получить любой объект API при необходимости в классе LoginService . Поэтому я пытаюсь использовать 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

    }

// интерфейс 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>

}

Получение сбоя, говорящего "lateinit" Свойство не инициализируется при попытке вызвать метод "loginWithOrg"

Насколько я понимаю, однажды определив и предоставив через модуль, я могу получить объект через @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 Ответ

0 голосов
/ 21 января 2019

Поскольку вы смешиваете две независимые вещи: инжекцию члена через void inject(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
) {
    ...
}

У вас есть эти классы, поэтому нетпричина использовать @field:Inject lateinit var + void inject(MyClass myClass); здесь.

...