MPAndroidChart堆叠柱状图刷新后增选币种崩溃问题排查
Android MPAndroidChart 堆叠柱状图刷新崩溃问题修复
问题概述
开发的Android应用使用MPAndroidChart展示堆叠柱状图,集成SwipeRefreshLayout后出现崩溃:首次选择X种币种正常展示,刷新后选择X+1种币种时触发IndexOutOfBoundsException,崩溃点指向图例渲染逻辑。
崩溃根源分析
从堆栈信息和代码来看,崩溃由以下几个问题共同导致:
- 全局数据未清空:
myChartData作为全局可变列表,每次API调用成功后直接追加数据,未清空旧数据,导致新旧数据混合,且不同批次BarEntry的values数组长度(对应币种数量)不一致,触发图表内部逻辑错误。 - 方法参数误用:
prepareChart方法接收entries参数,但创建BarDataSet时错误使用了未定义的全局变量(推测为笔误的myEntries),导致DataSet绑定旧数据,与新的币种数量不匹配。 - 颜色列表生成缺陷:生成
colorsList时,若随机颜色重复则跳过添加,导致colorsList长度可能小于pickedCurrs的长度,后续创建LegendEntry时访问colorsList[i]触发数组越界。 - X轴格式化器参数错误:设置X轴格式化器时使用全局变量
myXAxisValues,而非方法传入的xAxisValues,导致X轴标签与当前数据不匹配。
修复步骤
1. 清空全局数据,避免累积
在API成功回调开始时,清空myChartData,确保每次使用全新数据:
is MyWrapper.Success -> { myChartData.clear() // 新增:清空旧数据 status.data?.timeSeriesRates?.entries?.forEachIndexed { index, entry -> myChartData.add( BarEntry( index.toFloat(), entry.value.values.map { it.toFloat() }.toFloatArray() ) ) } makeChart( myChartData, formatDate(status.data?.timeSeriesRates?.keys!!.toList()), mSelectedCurrencies ) }
2. 修正DataSet的数据源参数
在prepareChart中,使用方法参数entries创建BarDataSet,而非错误的全局变量:
// 原错误代码 // set = BarDataSet(myEntries, "x") // 修改为 set = BarDataSet(entries, "x")
3. 修复颜色列表生成逻辑
确保colorsList长度与币种数量一致,可通过循环生成不重复颜色,或允许颜色重复(根据业务需求选择):
方案一:生成不重复颜色
val colorsList = mutableListOf<Int>() for (i in pickedCurrs.indices) { var color: Int do { color = Color.argb( 255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256) ) } while (colorsList.contains(color)) // 循环直到生成唯一颜色 colorsList.add(color) }
方案二:允许颜色重复(简化逻辑)
val colorsList = mutableListOf<Int>() for (i in pickedCurrs.indices) { val color = Color.argb( 255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256) ) colorsList.add(color) // 直接添加,不判断重复 }
4. 修正X轴格式化器参数
使用方法传入的xAxisValues设置X轴格式化器:
// 原错误代码 // mBinding.timeSeriesChart.xAxis?.valueFormatter = IndexAxisValueFormatter(myXAxisValues) // 修改为 mBinding.timeSeriesChart.xAxis?.valueFormatter = IndexAxisValueFormatter(xAxisValues)
5. 可选:清空图表旧状态(增强稳定性)
在prepareChart方法开头,清空图表的旧数据和状态,避免残留:
private fun prepareChart( entries: MutableList<BarEntry>, xAxisValues: ArrayList<String>, pickedCurrs: MutableList<String> ) { mBinding.timeSeriesChart.clear() // 新增:清空旧图表状态 val colorsList = mutableListOf<Int>() // 后续代码不变 }
验证修复
完成上述修改后,测试以下场景:
- 首次选择X种币种,确认图表正常显示
- 刷新后选择X+1种币种,确认应用不崩溃,图表数据和图例正常展示
内容的提问来源于stack exchange,提问作者SlipperyBarrel
相关产品推荐
相关产品推荐

