我是 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/