kotlin 如果我在第一个选择器上选择回到上一个选择,NumberPicker将引发ArrayIndexOutOfBoundsException

xienkqul  于 2023-11-21  发布在  Kotlin
关注(0)|答案(1)|浏览(303)

所以我有两个NumberPicker,第二个选择器的数组将基于第一个选择器的选择。但是在下面的代码中,如果我从5 han中选择4 han,我会遇到以下异常

  1. java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
  2. at android.widget.NumberPicker.ensureCachedScrollSelectorValue(NumberPicker.java:2010)
  3. at android.widget.NumberPicker.initializeSelectorWheelIndices(NumberPicker.java:1822)
  4. at android.widget.NumberPicker.setMaxValue(NumberPicker.java:1520)
  5. at com.vincent.majcal.ui.picker.PickerFragment.onCreateView$lambda$1(PickerFragment.kt:114)

字符串
下面是这部分的代码,我使用了Bottom Nagivation View Activity模板,并用我自己的用途:修改了它:

  1. package com.vincent.majcal.ui.picker
  2. import android.os.Bundle
  3. import android.util.Log
  4. import android.view.LayoutInflater
  5. import android.view.View
  6. import android.view.ViewGroup
  7. import android.widget.NumberPicker
  8. import android.widget.Switch
  9. import android.widget.TextView
  10. import androidx.fragment.app.Fragment
  11. import androidx.lifecycle.ViewModelProvider
  12. import com.vincent.majcal.databinding.FragmentPickerTestBinding
  13. import com.vincent.majcal.databinding.FragmentSearchBinding
  14. class PickerFragment : Fragment() {
  15. private var _binding: FragmentPickerTestBinding? = null
  16. // This property is only valid between onCreateView and
  17. // onDestroyView.
  18. private val binding get() = _binding!!
  19. override fun onCreateView(
  20. inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
  21. ): View {
  22. val pickerViewModel = ViewModelProvider(this).get(PickerViewModel::class.java)
  23. _binding = FragmentPickerTestBinding.inflate(inflater, container, false)
  24. val root: View = binding.root
  25. val textView: TextView = binding.textSearch
  26. val firstPicker: NumberPicker = binding.firstPicker
  27. val secondPicker: NumberPicker = binding.secondPicker
  28. var fan = "1 han"
  29. val selections = mapOf(
  30. "1 han" to arrayOf(
  31. "30",
  32. "40",
  33. "50",
  34. "60",
  35. "70",
  36. "80",
  37. "90",
  38. "100",
  39. "110"
  40. ),
  41. "2 han" to arrayOf(
  42. "20",
  43. "25",
  44. "30",
  45. "40",
  46. "50",
  47. "60",
  48. "70",
  49. "80",
  50. "90",
  51. "100",
  52. "110"
  53. ),
  54. "3 han" to arrayOf(
  55. "20",
  56. "25",
  57. "30",
  58. "40",
  59. "50",
  60. "60",
  61. "70+",
  62. ),
  63. "4 han" to arrayOf(
  64. "20",
  65. "25",
  66. "30",
  67. "40+",
  68. ),
  69. "5 han" to arrayOf(
  70. "Mangan",
  71. ),
  72. "6 ~ 7 han" to arrayOf(
  73. "Haneman",
  74. ),
  75. "8 ~ 10 han" to arrayOf(
  76. "Baiman",
  77. ),
  78. "11 ~ 12 han" to arrayOf(
  79. "Sanbaiman",
  80. ),
  81. "13 han+" to arrayOf(
  82. "Kazoe Yakuman",
  83. )
  84. )
  85. firstPicker.minValue = 0
  86. firstPicker.maxValue = selections.keys.size - 1
  87. firstPicker.displayedValues = selections.keys.toTypedArray()
  88. firstPicker.wrapSelectorWheel = false
  89. secondPicker.wrapSelectorWheel = false
  90. secondPicker.minValue = 0
  91. // default the max value to the first Picker value set
  92. var secondDisplayArray = selections[fan]
  93. if (secondDisplayArray != null) {
  94. secondPicker.maxValue = secondDisplayArray.size - 1
  95. }
  96. secondPicker.displayedValues = secondDisplayArray
  97. firstPicker.setOnValueChangedListener { picker, oldVal, newVal ->
  98. run {
  99. fan = selections.keys.elementAt(newVal)
  100. secondDisplayArray = selections[fan]
  101. if (secondDisplayArray != null) {
  102. var secondDisplayArraySize: Int = secondDisplayArray!!.size
  103. secondPicker.value = 0
  104. secondPicker.maxValue = secondDisplayArraySize - 1 //the Logcat show this line cause the exception
  105. secondPicker.displayedValues = secondDisplayArray
  106. }
  107. }
  108. }
  109. pickerViewModel.text.observe(viewLifecycleOwner) {
  110. textView.text = it
  111. }
  112. return root
  113. }
  114. override fun onDestroyView() {
  115. super.onDestroyView()
  116. _binding = null
  117. }
  118. }

iyfamqjs

iyfamqjs1#

尝试更改firstPickerOnValueChangedListener中的操作顺序,以确保displayedValuesmaxValue之前更新。原因是secondPicker.maxValue = secondDisplayArraySize - 1发生在secondPicker.displayedValues = secondDisplayArray之前,因此如果NumberPicker尝试访问基于旧maxValue的值,(在设置新的displayedValues数组之前),这可能会导致超出边界,从而导致ArrayIndexOutOfBoundsException
我也会在更新其他变量之前清除secondPicker.value,以确保它在范围内。

  1. firstPicker.setOnValueChangedListener { picker, oldVal, newVal ->
  2. run {
  3. fan = selections.keys.elementAt(newVal)
  4. secondDisplayArray = selections[fan]
  5. if (secondDisplayArray != null) {
  6. var secondDisplayArraySize: Int = secondDisplayArray!!.size
  7. secondPicker.displayedValues = secondDisplayArray // Update displayedValues first
  8. secondPicker.maxValue = secondDisplayArraySize - 1 // Then update maxValue
  9. secondPicker.value = 0 // Ensure value is within bounds
  10. }
  11. }
  12. }

字符串

展开查看全部

相关问题