使用@Inject注入Drawable字段时遭遇[Dagger/Nullable]错误求助
这个错误的核心原因很清晰:你提供的Drawable可能为空,但注入的字段被声明为不可空类型,Dagger的空安全检查触发了这个报错。
问题分析
ContextCompat.getDrawable()的返回类型是Drawable?(Kotlin可空类型),这意味着它有可能返回null(比如资源ID错误、资源在某些系统版本中不存在)。而你在AuthActivity里注入的drawableLogo是lateinit var drawableLogo: Drawable——一个不可空的字段,Dagger会严格校验这种可空性不匹配,所以抛出了[Dagger/Nullable]错误。
解决方案
根据你的业务场景,有两种处理方式:
方案1:确保Drawable一定存在(推荐)
如果你确定R.drawable.logo这个资源在所有支持的设备和版本中都存在,可以修改AppModule中的provideAppDrawable方法,强制返回非空的Drawable,并在资源不存在时抛出异常:
@JvmStatic @Provides fun provideAppDrawable(application: Application): Drawable { return ContextCompat.getDrawable(application, R.drawable.logo) ?: throw IllegalArgumentException("Drawable R.drawable.logo not found! Check your resources.") }
或者用更简洁的!!(但要确保资源绝对存在,否则运行时会抛出NPE):
@JvmStatic @Provides fun provideAppDrawable(application: Application): Drawable = ContextCompat.getDrawable(application, R.drawable.logo)!!
这样Dagger就会认为这个提供的Drawable是不可空的,和你注入的字段类型匹配,错误就会消失。
方案2:允许Drawable为空
如果这个Drawable有可能不存在(比如是可选资源),那么需要修改注入字段的类型为可空,并在使用时处理null情况:
- 修改
AuthActivity中的注入字段:
@Inject var drawableLogo: Drawable? = null
- 在
setLogo方法中处理null:
fun setLogo() { drawableLogo?.let { logo -> requestManager.load(logo).into(loginLogo) } // 也可以添加else分支处理资源不存在的情况,比如显示默认图 }
额外说明
Dagger会自动识别Kotlin的空安全类型,以及Java的@Nullable/@NonNull注解。当你提供的对象可能为空,但注入的字段要求非空时,就会触发这类可空性不匹配的错误。保持提供方和注入方的可空性一致,就能避免这类问题。
内容的提问来源于stack exchange,提问作者DisplayName

