为何第二次遍历JSONObject的keys时循环未执行?
问题原因与解决方案
核心问题
你遇到的循环不执行的原因是:JSONObject.keys()返回的Iterator是一次性的。第一次遍历表头时,已经把迭代器里的所有元素取完,迭代器内部指针走到末尾。第二次复用这个迭代器时,hasNext()会直接返回false,所以循环不会执行——这是迭代器的正常行为,不会触发报错。
修复方案
把迭代器转换成可重复遍历的集合(比如List<String>),这样每次遍历都能从头开始获取元素。修改drawTable方法中获取keys的逻辑即可:
修改后的代码
override fun drawTable(jsonArrayData: JSONArray) { // ------ Draw the table ----- // Draw the keys first val headerRow = TableRow(requireActivity()) Log.d("jsonArray", jsonArrayData[0].toString()) val firstRecord = jsonArrayData[0] as JSONObject // 将迭代器转为List,支持重复遍历 val keys = firstRecord.keys().asSequence().toList() for (key in keys) { val textView = TextView(requireActivity()) textView.text = key headerRow.addView(textView) } binding.table.addView(headerRow) // Draw the data second for (i in 0 until jsonArrayData.length()) { val record = jsonArrayData[i] as JSONObject Log.d("Record", record.toString()) val tableRow = TableRow(requireActivity()) Log.d("Table Row", "Table Row created") Log.d("Keys", keys.toString()) // 现在可以正常遍历keys生成单元格 for (key in keys) { Log.d("key", key) val textView = TextView(requireActivity()) // 优化:避免强转String崩溃,转为安全的toString处理 val cellText = record[key]?.toString() ?: "" textView.text = cellText tableRow.addView(textView) } binding.table.addView(tableRow) } }
额外说明
- 迭代器特性:Java/Kotlin中的
Iterator是单向、一次性的遍历工具,遍历完成后无法重置或重新遍历,必须重新获取迭代器或者转换为可重复访问的集合。 - 类型安全优化:原代码中
record[key] as String如果遇到非String类型的JSON值(比如数字、布尔值)会抛出ClassCastException,改用record[key]?.toString() ?: ""可以避免崩溃,同时兼容不同数据类型。
内容的提问来源于stack exchange,提问作者David Frick
相关产品推荐
相关产品推荐

