根据调试器,onSelectionChanged中引用的任何变量都为null,并且如果我运行示例应用程序并将以下内容添加到简单布局中,则应用程序将因nullpointer崩溃而崩溃。

 <com.dummy.DummyEditText
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
自定义AppCompatEditText的最简单示例
package com.dummy

import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatEditText

class DummyEditText : AppCompatEditText {

    constructor(context: Context) : super(context)
    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private val a = String()
    override fun onSelectionChanged(selStart: Int, selEnd: Int) {
        a.toString()
    }
}
与堆栈跟踪
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toString()' on a null object reference
        at com.dummy.DummyEditText.onSelectionChanged(DummyEditText.kt:15)
2020-10-05 12:14:25.794 22859-22859/com.dummy E/AndroidRuntime:     at android.widget.TextView.spanChange(TextView.java:10744)
        at android.widget.TextView$ChangeWatcher.onSpanAdded(TextView.java:13600)
        at android.text.SpannableStringBuilder.sendSpanAdded(SpannableStringBuilder.java:1287)
        at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:777)
        at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:676)
        at android.text.Selection.setSelection(Selection.java:96)
        at android.text.Selection.setSelection(Selection.java:78)
        at android.text.Selection.setSelection(Selection.java:153)
        at android.text.method.ArrowKeyMovementMethod.initialize(ArrowKeyMovementMethod.java:312)
        at android.widget.TextView.setText(TextView.java:6299)
        at android.widget.TextView.setText(TextView.java:6139)
        at android.widget.EditText.setText(EditText.java:121)
        at android.widget.TextView.<init>(TextView.java:1642)
        at android.widget.EditText.<init>(EditText.java:87)
        at android.widget.EditText.<init>(EditText.java:83)
        at androidx.appcompat.widget.AppCompatEditText.<init>(AppCompatEditText.java:74)
        at androidx.appcompat.widget.AppCompatEditText.<init>(AppCompatEditText.java:69)
        at com.dummy.DummyEditText.<init>(DummyEditText.kt:10)
所以问题是为什么变量a为null?不管如何onSelectionChanged实例化,在DummyEditText中首次引用它时都应该实例化它。我在这里想念什么?
任何关于正在发生的事情的指针都表示赞赏!

最佳答案

在调试时,我发现在运行onSelectionChanged块之前已调用init
documentation中所述:

调用OnSelectionChanged时,属性尚未初始化。
因此,我相信,发生的事情是在一个父类(super class)中,构造函数中的某些代码必定导致onSelectionChanged被调用。因此,在初始化任何属性之前,都会调用onSelectionChanged,因此您的字段为null。
这是一个复制场景的示例:

open class Parent {
    init {
        demo()
    }

    open fun demo() {
        print("Base class function called")
    }
}

class Child() : Parent() {

    val demoText = "12345"
    override fun demo() {
        super.demo()

        println(demoText.toString()) // This line will throw a NPE as demoText is not yet instantiated
    }
}

10-07 12:48