Я не могу понять, почему это выбрасывает NPE на линии when (colorState)
. Если я удаляю enum 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 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)
case, то получу еще один NPE, на этот раз, потому что stateAccent
еще не инициализирован - что на данный момент имеет смысл.