PhilJay / MPAndroidChart

A powerful 🚀 Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, panning and animations.
Other
37.67k stars 9.02k forks source link

AxisBase.mEntries can be out of sync with the data. #2447

Open cxzhang2 opened 8 years ago

cxzhang2 commented 8 years ago

The culprit is this if statement (AxisRenderer.java, line 225):

image

When reducing the # of entries through notifyDataSetChanged(), n can be calculated to be smaller than mEntries.length, resulting in mEntries with values that don't belong in the new, smaller data set.

This becomes a problem when a ValueFormatter maps value via some user-defined collection/function that is only equipped to handle values current data set. IndexOutOfBounds/NullPointer exceptions can occur.

Thoughts on changing the condition to mAxis.mEntries.length != n instead? Looks like the < is only for performance.

ashalmawia commented 1 year ago

In case someone is wondering if this is happening in practice, it does. I am using the same LineChart with variable time ranges, so amount of points can vary (30 for month view, 12 for year view). I read labels from an external array which size is equal to the size of the array. (Link to the code.)

When switching from 30 points to 12, I almost 100% get an IndexOutOfBoundsException - seems like setData() is trying to format an old value while it should not be in use anymore?

Workaround is easy, but the issue is annoying as it took some time to figure it out. Happy to see that there is a solution already! FYI @PhilJay

Stacktrace:

2023-07-16 00:40:37.908 32206-32206 AndroidRuntime          com.ashalmawia.coriolan.debug        E  FATAL EXCEPTION: main
    Process: com.ashalmawia.coriolan.debug, PID: 32206
    java.lang.IndexOutOfBoundsException: Index: 30, Size: 12
     at java.util.ArrayList.get(ArrayList.java:437)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsPanelLineChart$setUpLineChart$formatter$1.getAxisLabel(StatisticsPanelLineChart.kt:35)
     at com.github.mikephil.charting.components.AxisBase.getFormattedLabel(AxisBase.java:488)
     at com.github.mikephil.charting.components.AxisBase.getLongestLabel(AxisBase.java:474)
     at com.github.mikephil.charting.renderer.XAxisRenderer.computeSize(XAxisRenderer.java:78)
     at com.github.mikephil.charting.renderer.XAxisRenderer.computeAxisValues(XAxisRenderer.java:73)
     at com.github.mikephil.charting.renderer.XAxisRenderer.computeAxis(XAxisRenderer.java:66)
     at com.github.mikephil.charting.charts.BarLineChartBase.notifyDataSetChanged(BarLineChartBase.java:346)
     at com.github.mikephil.charting.charts.Chart.setData(Chart.java:300)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsPanelLineChart.setUpLineChart(StatisticsPanelLineChart.kt:72)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsFragment.setUpCardsLearntByDayPanel(StatisticsFragment.kt:85)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsFragment.initializePanels(StatisticsFragment.kt:73)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsFragment.access$initializePanels(StatisticsFragment.kt:31)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsFragment$setUpDateRangePicker$1$1.invoke(StatisticsFragment.kt:127)
     at com.ashalmawia.coriolan.ui.main.statistics.StatisticsFragment$setUpDateRangePicker$1$1.invoke(StatisticsFragment.kt:126)
     at com.ashalmawia.coriolan.ui.view.ViewExtentionsKt$setOnItemSelectedListener$1.onItemSelected(ViewExtentions.kt:31)
     at android.widget.AdapterView.fireOnSelected(AdapterView.java:957)
     at android.widget.AdapterView.dispatchOnItemSelected(AdapterView.java:946)
     at android.widget.AdapterView.-$$Nest$mdispatchOnItemSelected(Unknown Source:0)
     at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:910)
     at android.os.Handler.handleCallback(Handler.java:942)
     at android.os.Handler.dispatchMessage(Handler.java:99)
     at android.os.Looper.loopOnce(Looper.java:201)
     at android.os.Looper.loop(Looper.java:288)
     at android.app.ActivityThread.main(ActivityThread.java:7872)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
---------------------------- PROCESS ENDED (32206) fo