简体   繁体   English

声明为不可为空的 Kotlin 属性即使具有初始化值也是可为空的

[英]Kotlin property declared as non-nullable is nullable even if it has initialized value

This is really interesting situation.这是非常有趣的情况。 I have some android custom view.我有一些 android 自定义视图。 It has some property 'state' for changing the drawable state of checkbox based on this property.它有一些属性 'state' 用于根据此属性更改复选框的可绘制状态。 As you can see, this property is declared as non-nullable and I initialize it with default value 'State.Regular'.如您所见,此属性被声明为不可为空,并且我使用默认值“State.Regular”对其进行了初始化。

class SomeCustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatCheckBox(context, attrs) {

    sealed class State {
        object Regular : State()
        object Specific : State()
    }

    // todo: it will be nice to implement statesaving
    //       but it's okay for now
    var state: State = State.Regular
        set(value) {
            field = value
            refreshDrawableState()
        }

    override fun onCreateDrawableState(extraSpace: Int): IntArray =
        super.onCreateDrawableState(extraSpace + 1).apply {
            val stateAttrRes = when(state) {
                State.Specific -> R.attr.some_custom_view_specific
                State.Regular -> R.attr.some_custom_view_regular
            }

            View.mergeDrawableStates(this, intArrayOf(stateAttrRes))
        }
}

But when we're going to use this view, it's crashing with this exception:但是当我们要使用这个视图时,它会因为这个异常而崩溃:

kotlin.NoWhenBranchMatchedException

I had tried to debug the when-expression and I have noticed that inside 'onCreateDrawableState' method it is not initialized with default value 'State.Regular', but with 'null', and that is why we have this 'NoWhenBranchMatchedException'.我曾尝试调试 when 表达式,我注意到在“onCreateDrawableState”方法中,它没有用默认值“State.Regular”初始化,而是用“null”初始化,这就是为什么我们有这个“NoWhenBranchMatchedException”。

Do you have any ideas why is this property initialized with null and how to fix this?你知道为什么这个属性用 null 初始化以及如何解决这个问题吗?

It isn't just for Kotlin.它不仅适用于 Kotlin。 You have this problem in Java too.你在 Java 中也有这个问题。 So It's better to ignore it by check it is not null or set a default value.所以最好通过检查它不为空或设置默认值来忽略它。

OnCreateDrawableState is calling before init block in Kotlin. OnCreateDrawableState 在 Kotlin 中的 init 块之前调用。 After init, your properties will initialize初始化后,您的属性将初始化

The problem is that the AppCompatCheckBox 's constructor (which calls onCreateDrawableState ) is called before SomeCustomView 's which initializes the property.问题是AppCompatCheckBox的构造函数(调用onCreateDrawableState )在初始化属性的SomeCustomView之前调用。 If you didn't need a custom setter you could use lateinit and initialize it inside onCreateDrawableState ;如果您不需要自定义设置器,您可以使用lateinit并在onCreateDrawableState lateinit进行初始化; with it, consider these workarounds (but they may be too complex for just this one place).有了它,请考虑这些解决方法(但对于仅此一个地方而言,它们可能太复杂了)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM