当表达式不适用于 onCreateDrawableState - android 中的枚举 class 时,kotlin
When expression not working with enum class in onCreateDrawableState - android, kotlin
我不明白为什么这会在 when (colorState)
行抛出 NPE。如果我删除枚举 class 并将值替换为整数,一切正常。
class ColorChangerButton(context: Context, attrs: AttributeSet) : AppCompatImageButton(context, attrs) {
enum class ColorState {ACCENT, STRONG, WEAK}
private val stateAccent = intArrayOf(R.attr.state_accent)
private val stateStrong = intArrayOf(R.attr.state_strong)
private val stateWeak = intArrayOf(R.attr.state_weak)
var colorState = ColorState.ACCENT
set(value) {
if (field != value) {
field = value
refreshDrawableState()
}
}
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val state = super.onCreateDrawableState(extraSpace + 1)
when (colorState) {
ColorState.ACCENT -> View.mergeDrawableStates(state, stateAccent)
ColorState.STRONG -> View.mergeDrawableStates(state, stateStrong)
ColorState.WEAK -> View.mergeDrawableStates(state, stateWeak)
}
return state
}
}
堆栈跟踪:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.test.uiplayground.buttons.ColorChangerButton$ColorState.ordinal()' on a null object reference
at com.test.uiplayground.buttons.ColorChangerButton.onCreateDrawableState(ColorChangerButton.kt:28)
at android.view.View.getDrawableState(View.java:15953)
at android.view.View.setBackgroundDrawable(View.java:16188)
at androidx.appcompat.widget.AppCompatImageButton.setBackgroundDrawable(AppCompatImageButton.java:122)
at android.view.View.setBackground(View.java:16125)
at android.view.View.<init>(View.java:4090)
at android.widget.ImageView.<init>(ImageView.java:139)
at android.widget.ImageButton.<init>(ImageButton.java:86)
at android.widget.ImageButton.<init>(ImageButton.java:82)
at androidx.appcompat.widget.AppCompatImageButton.<init>(AppCompatImageButton.java:73)
at androidx.appcompat.widget.AppCompatImageButton.<init>(AppCompatImageButton.java:69)
at com.test.uiplayground.buttons.ColorChangerButton.<init>(ColorChangerButton.kt:9)
正如我上面所说,如果我将枚举 class 替换为整数,那么它工作得很好:
class ColorChangerButton(context: Context, attrs: AttributeSet) : AppCompatImageButton(context, attrs) {
private val stateAccent = intArrayOf(R.attr.state_accent)
private val stateStrong = intArrayOf(R.attr.state_strong)
private val stateWeak = intArrayOf(R.attr.state_weak)
var colorState = 1
set(value) {
if (field != value) {
field = value
refreshDrawableState()
}
}
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val state = super.onCreateDrawableState(extraSpace + 1)
when (colorState) {
1 -> View.mergeDrawableStates(state, stateAccent)
2 -> View.mergeDrawableStates(state, stateStrong)
3 -> View.mergeDrawableStates(state, stateWeak)
}
return state
}
}
已解决,补充说明:
- 关于抛出 NPE 的原因,请参阅已接受的答案。
- 整数部分具有误导性。 Java 将未初始化的变量设置为默认值(除非是局部变量或块变量,否则您会收到错误消息说它未初始化)。对于整数,该值为 0。因此它在第一次调用时通过了所有 3 个条件。如果我添加
0 -> View.mergeDrawableStates(state, stateAccent)
案例,那么我会得到另一个 NPE,这次是因为 stateAccent
尚未初始化 - 现在这很有意义。
这是为 Kotlin 源文件生成的 Java 代码:
public ColorChangerButton(@NotNull Context context, @NotNull AttributeSet attrs) {
Intrinsics.checkParameterIsNotNull(context, "context");
Intrinsics.checkParameterIsNotNull(attrs, "attrs");
super(context, attrs); <---------- super will be called first
this.stateAccent = new int[0];
this.stateStrong = new int[0];
this.stateWeak = new int[0];
this.colorState = ColorChangerButton.ColorState.ACCENT;
}
在调用 super()
之前,实例变量甚至不会被初始化。当超级构造函数调用 onCreateDrawableState
时发生 NPE。
我不明白为什么这会在 when (colorState)
行抛出 NPE。如果我删除枚举 class 并将值替换为整数,一切正常。
class ColorChangerButton(context: Context, attrs: AttributeSet) : AppCompatImageButton(context, attrs) {
enum class ColorState {ACCENT, STRONG, WEAK}
private val stateAccent = intArrayOf(R.attr.state_accent)
private val stateStrong = intArrayOf(R.attr.state_strong)
private val stateWeak = intArrayOf(R.attr.state_weak)
var colorState = ColorState.ACCENT
set(value) {
if (field != value) {
field = value
refreshDrawableState()
}
}
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val state = super.onCreateDrawableState(extraSpace + 1)
when (colorState) {
ColorState.ACCENT -> View.mergeDrawableStates(state, stateAccent)
ColorState.STRONG -> View.mergeDrawableStates(state, stateStrong)
ColorState.WEAK -> View.mergeDrawableStates(state, stateWeak)
}
return state
}
}
堆栈跟踪:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.test.uiplayground.buttons.ColorChangerButton$ColorState.ordinal()' on a null object reference
at com.test.uiplayground.buttons.ColorChangerButton.onCreateDrawableState(ColorChangerButton.kt:28)
at android.view.View.getDrawableState(View.java:15953)
at android.view.View.setBackgroundDrawable(View.java:16188)
at androidx.appcompat.widget.AppCompatImageButton.setBackgroundDrawable(AppCompatImageButton.java:122)
at android.view.View.setBackground(View.java:16125)
at android.view.View.<init>(View.java:4090)
at android.widget.ImageView.<init>(ImageView.java:139)
at android.widget.ImageButton.<init>(ImageButton.java:86)
at android.widget.ImageButton.<init>(ImageButton.java:82)
at androidx.appcompat.widget.AppCompatImageButton.<init>(AppCompatImageButton.java:73)
at androidx.appcompat.widget.AppCompatImageButton.<init>(AppCompatImageButton.java:69)
at com.test.uiplayground.buttons.ColorChangerButton.<init>(ColorChangerButton.kt:9)
正如我上面所说,如果我将枚举 class 替换为整数,那么它工作得很好:
class ColorChangerButton(context: Context, attrs: AttributeSet) : AppCompatImageButton(context, attrs) {
private val stateAccent = intArrayOf(R.attr.state_accent)
private val stateStrong = intArrayOf(R.attr.state_strong)
private val stateWeak = intArrayOf(R.attr.state_weak)
var colorState = 1
set(value) {
if (field != value) {
field = value
refreshDrawableState()
}
}
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val state = super.onCreateDrawableState(extraSpace + 1)
when (colorState) {
1 -> View.mergeDrawableStates(state, stateAccent)
2 -> View.mergeDrawableStates(state, stateStrong)
3 -> View.mergeDrawableStates(state, stateWeak)
}
return state
}
}
已解决,补充说明:
- 关于抛出 NPE 的原因,请参阅已接受的答案。
- 整数部分具有误导性。 Java 将未初始化的变量设置为默认值(除非是局部变量或块变量,否则您会收到错误消息说它未初始化)。对于整数,该值为 0。因此它在第一次调用时通过了所有 3 个条件。如果我添加
0 -> View.mergeDrawableStates(state, stateAccent)
案例,那么我会得到另一个 NPE,这次是因为stateAccent
尚未初始化 - 现在这很有意义。
这是为 Kotlin 源文件生成的 Java 代码:
public ColorChangerButton(@NotNull Context context, @NotNull AttributeSet attrs) {
Intrinsics.checkParameterIsNotNull(context, "context");
Intrinsics.checkParameterIsNotNull(attrs, "attrs");
super(context, attrs); <---------- super will be called first
this.stateAccent = new int[0];
this.stateStrong = new int[0];
this.stateWeak = new int[0];
this.colorState = ColorChangerButton.ColorState.ACCENT;
}
在调用 super()
之前,实例变量甚至不会被初始化。当超级构造函数调用 onCreateDrawableState
时发生 NPE。