【问题标题】:NullPointerException (NPE) when using Kotlin property delegate with by将 Kotlin 属性委托与 by 一起使用时出现 NullPointerException (NPE)
【发布时间】:2020-11-17 07:28:59
【问题描述】:

我有一个类,它在文本字段中接受用户输入并使用提供的函数将它们转换为任何类

class GenericTextFieldDelegate<T>(
    private val initBlock: () -> TextView,
    private val getConversion: (String?) -> T?,
    private val setConversion: (T?) -> String? = { it?.toString() }
    ) {
    private val textView: TextView by lazy { initBlock() }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T? =
        getConversion(textView.text?.toString())

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
        textView.text = setConversion(value)
    }
}

我这样做是为了当我有 TextViews 时我可以这样做

class IntegerInputView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attributeSet, defStyleAttr), DataInput<Int> {

override var value: Int? by GenericTextFieldDelegate(
    { inputET },
    getConversion = { it?.toIntOrNull() },
    setConversion = { it.toString() }
)
...

我有一个具有上述自定义视图的片段,当我有时

override var tareWeight: Kg?
    get() = tareWeightInput.value
    set(value) {
        tareWeightInput.value = value
    }

一切正常,我真正想做的是

override var tareWeight: Kg? by tareWeightInput

将这些行添加到IntegerInputView

...

operator fun getValue(thisRef: Any?, property: KProperty<*>): Int? = value

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int?) {
    this.value = value
}

override var value: Int? by GenericTextFieldDelegate(
...

当我构建、运行和加载片段时,我得到下面的堆栈跟踪。我哪里错了?

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Integer com.gameforeverything.storekeeper.customViews.IntegerInputView.getValue(java.lang.Object, kotlin.reflect.KProperty)' on a null object reference
        at com.gameforeverything.storekeeper.fragments.weighInFragment.WeighInFragment.getGrossWeight(Unknown Source:7)
        at com.gameforeverything.storekeeper.fragments.weighInFragment.WeighInPresenter.getNetWeight(WeighInPresenter.kt:40)

【问题讨论】:

    标签: android kotlin nullpointerexception kotlin-delegate


    【解决方案1】:

    您的属性委托本身(本例中为tareWeightInput)为空。

    您可以通过检查堆栈跟踪来判断是这种情况:它注意到由于 NPE 而失败的方法调用是IntegerInputView.getValue。由于这是在委托上调用属性委托方法调用以检索属性值,因此我们知道委托必须为空。

    您的属性委托是View,所以我怀疑它正在以某种方式动态检索,可能是findViewById 调用的结果。您需要确保包含委托的变量在检索时不为空。考虑这个类似的例子:

    import kotlin.reflect.KProperty
    
    class FooDelegate {
        private var value: Int = 0
        operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
    }
    
    class Foo {
        private lateinit var delegate: FooDelegate
        val bar by delegate
        
        init {
            delegate = FooDelegate()
        }
    }
    
    fun main() {
        println(Foo().bar)
    }
    

    这会崩溃,因为它试图在变量初始化之前设置委托。在这种情况下,Kotlin 会更早地抛出错误,但由于 Kotlin/Java 互操作,这可能在您的示例中被 platform types 掩盖。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-04
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-08
      相关资源
      最近更新 更多