Dagger does not support injection into private fields
这是因为在 Kotlin
中,Field
生成的 Java
代码都是都是带 get
和 set
的,然后 Field
是要设置为 private
的,下面就是生成的代码
@Nullable
@Inject
private volatile DispatchingAndroidInjector androidInjector;
@Nullable
public final DispatchingAndroidInjector getAndroidInjector() {
return this.androidInjector;
}
public final void setAndroidInjector(@Nullable DispatchingAndroidInjector var1) {
this.androidInjector = var1;
}
这种情况我们有两种方法解决
第一种,让它变回 Java 原本的样子
增加 JvmField
@Inject
@JvmField
var androidInjector: DispatchingAndroidInjector<Any?>? = null
这样生成的代码就会变成
@Inject
@JvmField
@Nullable
public volatile DispatchingAndroidInjector androidInjector;
这样就完全没有问题了,但是这样会把属性暴露出去,不是很好。因为kotlin是没有包内属性的,你也改不了为包内属性。
第二种,设置 set
方法为 Inject
以为 dagger
是支持注入方法的,直接标记属性的 setter 方法也能解决这问题,代码如下
@Volatile
@set:Inject
var androidInjector: DispatchingAndroidInjector<Any?>? = null
对应的 Java代码就会变成这样
@Nullable
private DispatchingAndroidInjector androidInjector;
@Nullable
public final DispatchingAndroidInjector getAndroidInjector() {
return this.androidInjector;
}
@Inject
public final void setAndroidInjector(@Nullable DispatchingAndroidInjector var1) {
this.androidInjector = var1;
}
这是一个比较好的实现,不会影响原有的访问域,代码编写也比较方便
这里有个小问题
如果你在 Android Studio 3.5到 3.6 编译这个代码,会报下面这个错误
An exception occurred: java.lang.IllegalArgumentException: not a > valid name:
Provider
但是,用命令行编译是没有问题的,所以我把 Android Studio 升级到 4.0,重新编译之后就没有这个问题。
上面没用,乖乖用 lateinit var
啥事都没有