Android Kotlin足球问答应用IndexOutOfBoundsException崩溃问题
足球问答应用崩溃问题排查与解决
问题概述
使用Kotlin开发Android足球问答应用,功能为展示球员图片并提供四个包含正确答案的选项按钮,要求每次启动生成新题目与不同错误选项。但应用在从MainActivity跳转至QuizActivity时或点击选项按钮时频繁崩溃,报错IndexOutOfBoundsException(例如:Index: 7, Size:6)。
错误日志
FATAL EXCEPTION: main Process: com.example.footballquizapp, PID: 8219 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.footballquizapp/com.example.footballquizapp.QuizActivity}: java.lang.IndexOutOfBoundsException: Index: 7, Size: 6 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3162) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3305) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1993) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:216) at android.app.ActivityThread.main(ActivityThread.java:7266) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975) Caused by: java.lang.IndexOutOfBoundsException: Index: 7, Size: 6 at java.util.ArrayList.get(ArrayList.java:437) at com.example.footballquizapp.QuizActivity.generateQuestion(QuizActivity.kt:58) at com.example.footballquizapp.QuizActivity.onCreate(QuizActivity.kt:37) at android.app.Activity.performCreate(Activity.java:7353) at android.app.Activity.performCreate(Activity.java:7344) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1275) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3142) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3305) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1993) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:216) at android.app.ActivityThread.main(ActivityThread.java:7266) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
问题根源
从错误日志可见,崩溃发生在generateQuestion方法中访问imageList[index]时。查看代码发现:
playerList包含8个球员名称,但imageList仅添加了6个图片资源,两者数量不一致- 当随机生成的
index为6或7时,imageList没有对应索引的元素,直接触发数组越界异常
早期版本中btnWithCorrectAnswer方法每次调用都会重新生成题目,也会导致索引越界,虽已修复,但核心的列表数量不匹配问题未解决。
修复方案
1. 对齐球员名称与图片资源数量
选择以下两种方式之一:
- 补全图片资源:为
Josua Kimmich和David Alaba添加对应的图片资源,并更新imageList:
private fun initializeViewsAndLists() { // ... 其他视图初始化 imageList = ArrayList<Int>() imageList.add(R.drawable.neymar) imageList.add(R.drawable.ronaldo) imageList.add(R.drawable.messi) imageList.add(R.drawable.mueller) imageList.add(R.drawable.mbappe) imageList.add(R.drawable.robben) imageList.add(R.drawable.kimmich) // 添加对应图片 imageList.add(R.drawable.alaba) // 添加对应图片 }
- 移除无图片的球员:从
playerList中删除没有对应图片的球员:
private fun initializeViewsAndLists() { // ... 其他视图初始化 playerList = ArrayList<String>() playerList.add("Neymar Junior") playerList.add("Cristiano Ronaldo") playerList.add("Lionel Messi") playerList.add("Thomas Müller") playerList.add("Killian Mbappe") playerList.add("Arian Robben") // 移除无对应图片的球员 // playerList.add("Josua Kimmich") // playerList.add("David Alaba") }
2. 使用数据类封装球员数据(推荐)
通过数据类将球员名称与图片资源绑定,从根源避免列表不同步问题:
// 定义球员数据类 data class Player(val name: String, val imageRes: Int) class QuizActivity : AppCompatActivity() { // ... 其他视图变量 lateinit var players: List<Player> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_quiz) initializeViewsAndLists() val question = generateQuestion() val correctPlayer = question.first val options = question.second btnFirstAns.text = options[0] btnSecondAns.text = options[1] btnThirdAns.text = options[2] btnFourthAns.text = options[3] imageView.setImageResource(correctPlayer.imageRes) // 设置点击事件 btnFirstAns.setOnClickListener { checkAnswer(btnFirstAns.text.toString(), correctPlayer.name) } btnSecondAns.setOnClickListener { checkAnswer(btnSecondAns.text.toString(), correctPlayer.name) } btnThirdAns.setOnClickListener { checkAnswer(btnThirdAns.text.toString(), correctPlayer.name) } btnFourthAns.setOnClickListener { checkAnswer(btnFourthAns.text.toString(), correctPlayer.name) } } fun generateQuestion(): Pair<Player, List<String>> { val correctPlayer = players.random() val wrongAnswers = players.filter { it != correctPlayer }.map { it.name }.shuffled().take(3) val options = (wrongAnswers + correctPlayer.name).shuffled() return Pair(correctPlayer, options) } private fun initializeViewsAndLists() { // ... 视图初始化 players = listOf( Player("Neymar Junior", R.drawable.neymar), Player("Cristiano Ronaldo", R.drawable.ronaldo), Player("Lionel Messi", R.drawable.messi), Player("Thomas Müller", R.drawable.mueller), Player("Killian Mbappe", R.drawable.mbappe), Player("Arian Robben", R.drawable.robben), Player("Josua Kimmich", R.drawable.kimmich), Player("David Alaba", R.drawable.alaba) ) } // ... 其他方法保持不变 }
3. 优化正确按钮查找逻辑
在生成题目时直接记录正确选项的文本,避免重复遍历按钮:
// 可以在类中添加变量记录当前正确选项文本 lateinit var currentCorrectAnswer: String // 在onCreate中赋值 currentCorrectAnswer = correctPlayer.name // 简化btnWithCorrectAnswer方法 fun btnWithCorrectAnswer(): Button? { return when(currentCorrectAnswer) { btnFirstAns.text -> btnFirstAns btnSecondAns.text -> btnSecondAns btnThirdAns.text -> btnThirdAns btnFourthAns.text -> btnFourthAns else -> null } }
内容的提问来源于stack exchange,提问作者Jakob Gabriel
相关产品推荐
相关产品推荐

