MPAndroidChart icon indicating copy to clipboard operation
MPAndroidChart copied to clipboard

[BUG] Combined chart BarData.getDataSetCount() null pointer exception

Open VadimTheCoder opened this issue 7 years ago • 6 comments

I have Combined chart which builds in 2 different ways (Line chart or Candle + Line + Bar chart). On first load both ways works fine (init app with 1st way or 2nd - ok).

If i draw 2nd group of charts and then try to draw first Line chart - i'm getting NPE: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.github.mikephil.charting.data.BarData.getDataSetCount()' on a null object reference

on that line of code: mCombinedChart.setData(combinedData);

I think i need to clear chart somehow or it is bug?

my code: private void buildChart(ArrayList<GraphPoint> graphData, final CoinExchangeData coin) { mCombinedChart.clear();

    //axis

    YAxis yAxisRight = mCombinedChart.getAxisRight();
    yAxisRight.setSpaceBottom(220f);
    yAxisRight.setEnabled(true);
    yAxisRight.setTextColor(getResources().getColor(R.color.landscape_chart_text_active));

    YAxis yAxisLeft = mCombinedChart.getAxisLeft();
    yAxisLeft.setEnabled(false);

    XAxis xAxis = mCombinedChart.getXAxis();
    xAxis.setEnabled(false);
    xAxis.setTextColor(getResources().getColor(R.color.landscape_chart_text_active));
    xAxis.setValueFormatter(new XAxisValueFormatter(graphData));

    mCombinedChart.setTouchEnabled(true);
    mCombinedChart.setHighlightPerDragEnabled(true);
    mCombinedChart.setHighlightPerTapEnabled(true);


    mCombinedChart.getDescription().setEnabled(false);

    mCombinedChart.setScaleEnabled(false);
    mCombinedChart.setDoubleTapToZoomEnabled(false);

    mCombinedChart.setNoDataText(App.getContext().getResources().getString(R.string.graph_no_data));

    //Line chart
    if (App.getPreferencesInstance().getInt(PreferencesManager.LANDSCAPE_CHART_MODE_KEY, PreferencesManager.LANDSCAPE_CHART_MODE_LINE) == PreferencesManager.LANDSCAPE_CHART_MODE_LINE) {
        mCombinedChart.getLegend().setEnabled(false);

        Legend legend = mCombinedChart.getLegend();
        legend.setEnabled(true);
        legend.setTextColor(getResources().getColor(R.color.landscape_chart_legend));
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);

        List<Entry> values = new ArrayList<>();

        for (int i = GRAPH_OFFSET; i < graphData.size(); ++i) {
            values.add(new Entry((float) i, graphData.get(i).high.floatValue()));
        }

        LineDataSet lineDataSet = new LineDataSet(values, coin.symbol);
        lineDataSet.setDrawValues(false);
        lineDataSet.setDrawCircles(false);
        lineDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);

        chartMin =  lineDataSet.getYMin();
        chartMax = lineDataSet.getYMax();
        mCombinedChart.getAxisRight().setAxisMinimum(chartMin);
        mCombinedChart.getAxisRight().setAxisMaximum(chartMax);


        lineDataSet.setDrawFilled(true);
        lineDataSet.setFillDrawable(LandscapeChartActivity.this.getResources().getDrawable(R.drawable.gradient_landscape_chart));


        lineDataSet.setColor(LandscapeChartActivity.this.getResources().getColor(R.color.landscape_chart_gold));
        lineDataSet.setLineWidth(2.0f);

        LineData lineData = new LineData(lineDataSet);

        if (lineData.getEntryCount() == 0) {
            showChartReload();
            return;
        }

        CombinedData combinedData = new CombinedData();
        combinedData.setData(lineData);

        mCombinedChart.setData(combinedData);
    } else {  // Candle chart
        List<CandleEntry> valuesRateData = new ArrayList<>();
        List<BarEntry> valuesVolumeData = new ArrayList<>();

        for (int i = GRAPH_OFFSET; i < graphData.size(); ++i) {
            GraphPoint graphPoint = graphData.get(i);

            valuesRateData.add(new CandleEntry((float) i - GRAPH_OFFSET, graphPoint.high.floatValue(), graphPoint.low.floatValue(),
                    graphPoint.open.floatValue(), graphPoint.close.floatValue()));
            valuesVolumeData.add(new BarEntry((float) i - GRAPH_OFFSET, graphPoint.volume.floatValue()));
        }

        CandleDataSet candleDataSet = new CandleDataSet(valuesRateData, coin.fullName.concat(" (").concat(coin.symbol).concat(")"));
        candleDataSet.setDrawValues(false);

        BarDataSet barDataSet = new BarDataSet(valuesVolumeData, getResources().getString(R.string.volume));
        barDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
        barDataSet.setColor(getResources().getColor(R.color.landscape_chart_volumes_bars));

        //chart.getXAxis().setTextColor(getResources().getColor(R.color.graph_axis));
        //chart.getAxisRight().setTextColor(getResources().getColor(R.color.graph_axis));


        yAxisLeft.setSpaceTop(400f);
        yAxisLeft.setEnabled(false);

        yAxisRight.setSpaceBottom(20f);

        candleDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
        //candleDataSet.setDrawFilled(true);
        candleDataSet.setIncreasingColor(getResources().getColor(R.color.landscape_chart_green));
        candleDataSet.setDecreasingColor(getResources().getColor(R.color.landscape_chart_red));
        candleDataSet.setNeutralColor(getResources().getColor(R.color.landscape_chart_candle_shadow));
        candleDataSet.setShadowColor(getResources().getColor(R.color.landscape_chart_candle_shadow));
        candleDataSet.setIncreasingPaintStyle(Paint.Style.FILL);
        candleDataSet.setShadowWidth(0.66f);
        candleDataSet.setHighLightColor(getResources().getColor(R.color.landscape_chart_gold));

        CandleData candleData = new CandleData(candleDataSet);

        CombinedData combinedData = new CombinedData();
        combinedData.setData(candleData);

        BarData barData = new BarData(barDataSet);
        combinedData.setData(barData);

        if (App.getPreferencesInstance().getInt(PreferencesManager.LANDSCAPE_INDICATOR_KEY, PreferencesManager.LANDSCAPE_INDICATOR_WMA7) == PreferencesManager.LANDSCAPE_INDICATOR_WMA7) {
            ArrayList<PointXY> points = Indicators.evaluateIndicatorWMA7(graphData);

            List<Entry> valuesWMA7Data = new ArrayList<>();

            for (int i = 0; i < points.size(); ++i) {
                valuesWMA7Data.add(new Entry(points.get(i).x.floatValue(), points.get(i).y.floatValue()));
            }

            LineDataSet indicatorWMA7DataSet = new LineDataSet(valuesWMA7Data, "WMA7");
            indicatorWMA7DataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
            indicatorWMA7DataSet.setColor(getResources().getColor(R.color.landscape_chart_indicator));
            indicatorWMA7DataSet.setDrawCircles(false);
            indicatorWMA7DataSet.setLineWidth(1.2f);

            LineData lineDataWMA7 = new LineData(indicatorWMA7DataSet);

            combinedData.setData(lineDataWMA7);
        }

        mCombinedChart.setData(combinedData);
    }
    showChart(coin);
}

VadimTheCoder avatar Jun 26 '18 08:06 VadimTheCoder

Found source code, where that bug happens:

in CombinedChartRenderer

@Override public void initBuffers() {

    for (DataRenderer renderer : mRenderers)
        renderer.initBuffers();
}

When redrawing Line chart after drawing 3 charts it calls initBuffers with previous values (Line, Bar and Candle)

VadimTheCoder avatar Jun 26 '18 08:06 VadimTheCoder

I met the same problem, A bad solution: combinedData.setData(barData()); before combinedData.setData(otherData);

Nccssa avatar Aug 01 '18 06:08 Nccssa

I have same problem. My solution : chart.setData(null); chart.setData(newData);

ShockUtility avatar Aug 01 '18 19:08 ShockUtility

I have same problem. My solution : chart.setData(null); chart.setData(newData);

Great Bro. It fix the problem!!

bastos1505 avatar Nov 29 '18 14:11 bastos1505

CombinedData data = new CombinedData();

switch(data) { // Only for BarChart case BarChart LineData ld = new LineData(); ld.clearValues(); chartData.setData(ld); chartData.setData(barData); break;

// Only for LineChart case LineChart BarData bd = new BarData(); bd.clearValues(); chartData.setData(bd); chartData.setData(lineData); break;

// Both the Chart (Line & Bar Chart) case BothChart chartData.setData(lineData); chartData.setData(barData); }

zafar0501 avatar Sep 09 '19 16:09 zafar0501

I have same problem. My solution : chart.setData(null); chart.setData(newData);

also work for me

chpl-aspire-2 avatar Mar 26 '24 11:03 chpl-aspire-2