highcharts / highcharts-android

Android wrapper for Highcharts usage
Other
126 stars 30 forks source link

Chart not displaying in Android device #285

Closed Venkataramana0801 closed 1 month ago

Venkataramana0801 commented 2 months ago

In My application, to get the data I am using AsyncTask. new UsagegraphServ(getActivity(), new String[]{"07/29/2024"}, "Get60minIntervalUsageData").execute(); After successful data, I am calling setupGraph(GraphType.INIT); in the onPostExecute method of AsyncTask the following is the setupGraph method, and also I tried with sample value 100, but not displaying the graph and also tried with debugging all the values are setting the graph, but no luck

 private void setupGraph(GraphType type) { // type for preload chart view

        try {
            int columnWidth = 20;
            int columnSpace = 10;
            double maxNegativeUsage = 0;
            float minWeather = 0;

            chartView.theme = "grid-light";

            //map to list of usagemodel
            List<String> dateFormatList = new ArrayList<>();
            List<Float> amountList = new ArrayList<>();
            List<Float> usageList = new ArrayList<>();
            List<Float> demanUsageList = new ArrayList<>();
            List<Float> tempList = new ArrayList<>();
            List<Float> humidityList = new ArrayList<>();
            List<Float> heatIndexList = new ArrayList<>();
            List<Float> windSpeedList = new ArrayList<>();

            List<String> usageColorList = new ArrayList<>();

            for (int i = 0; i < usgListParsedVals.size(); i++) {
                dateFormatList.add(usgListParsedVals.get(i).get("UsageHourDateFormat"));

                if (usgListParsedVals.get(i).get("KWH").equalsIgnoreCase("nan"))
                    usageList.add(Float.parseFloat("100"));
                else
//                    usageList.add(Float.parseFloat(usgListParsedVals.get(i).get("KWH")));
                    usageList.add(Float.parseFloat("100"));

                if (usgListParsedVals.get(i).get("Temp").equalsIgnoreCase("nan"))
                    tempList.add(Float.parseFloat("0"));
                else
                    tempList.add(Float.parseFloat(usgListParsedVals.get(i).get("Temp")));

                if (usgListParsedVals.get(i).get("Humidity").equalsIgnoreCase("nan"))
                    humidityList.add(Float.parseFloat("0"));
                else
                    humidityList.add(Float.parseFloat(usgListParsedVals.get(i).get("Humidity")));

                if (usgListParsedVals.get(i).get("HeatIndex").equalsIgnoreCase("nan"))
                    heatIndexList.add(Float.parseFloat("0"));
                else
                    heatIndexList.add(Float.parseFloat(usgListParsedVals.get(i).get("HeatIndex")));

                if (usgListParsedVals.get(i).get("WindSpeed").equalsIgnoreCase("nan"))
                    windSpeedList.add(Float.parseFloat("0"));
                else
                    windSpeedList.add(Float.parseFloat(usgListParsedVals.get(i).get("WindSpeed")));

                usageColorList.add(usgListParsedVals.get(i).get("GraphColor"));

                strColorKwh = usgListParsedVals.get(0).get("GraphColor");
                strColorTemp = usgListParsedVals.get(0).get("TempGraphColor");
                strColorHumidity = usgListParsedVals.get(0).get("HumidityGraphColor");
                strColorHeat = usgListParsedVals.get(0).get("HeatIndexGraphColor");
                strColorWind = usgListParsedVals.get(0).get("WindSpeedGraphColor");

            }
            Log.e("Date ", "@@@" + dateFormatList.size());
            Log.e("usage ", "@@@" + usageList.size());

            HIOptions options = new HIOptions();
            options.setCredits(new HICredits());
            options.setExporting(new HIExporting());
            options.getCredits().setEnabled(false);
            options.getExporting().setEnabled(false);
            options.setColors(new ArrayList<>(usageColorList));

            int minWidth = (columnWidth + columnSpace) * dateFormatList.size();

            HIChart chart = new HIChart();
            chart.setScrollablePlotArea(new HIScrollablePlotArea());
            chart.getScrollablePlotArea().setMinWidth(minWidth);
            chart.getScrollablePlotArea().setScrollPositionX(0);

            options.setChart(chart);

            HITitle title = new HITitle();
            title.setText(""); // Chart Top Title
            options.setTitle(title);

            HISubtitle subtitle = new HISubtitle();
            subtitle.setText(""); // Chart second top title
            options.setSubtitle(subtitle);

            HIXAxis xaxis = new HIXAxis();
            if (type == GraphType.NULL) {
                xaxis.setCategories(new ArrayList<>(Arrays.asList()));
            } else {
                xaxis.setCategories(new ArrayList<>(dateFormatList));
            }

            options.setXAxis(new ArrayList<>(Collections.singletonList(xaxis)));

            HIYAxis yaxis = new HIYAxis();
            yaxis.setMin(maxNegativeUsage);
            yaxis.setStackLabels(new HIStackLabels());
            yaxis.getStackLabels().setEnabled(true);

            HITitle titleYaxis = new HITitle();
            HICSSObject titleStyle = new HICSSObject();
            //titleStyle.setColor(HIColor.initWithHexValue("#0E6F81"));
            titleYaxis.setStyle(titleStyle);
            titleYaxis.setText("Usage (kwh)");
            yaxis.setTitle(titleYaxis);

            HILabels hiLabelsYaxisOpposite = new HILabels();
            hiLabelsYaxisOpposite.setEnabled(true);

            HIYAxis yaxisOpposite = new HIYAxis();
            yaxisOpposite.setMin(minWeather);
            yaxisOpposite.setTitle(new HITitle());
//            yaxisOpposite.getTitle().setText(""); // Chart Left Title yaxis.getTitle().setText("Usage (Kwh)"); // Chart Left Title
            yaxisOpposite.setOpposite(true);
            yaxisOpposite.setType("temp");
            yaxisOpposite.setLabels(new HILabels());
            yaxisOpposite.getLabels().setFormat("{value}°F");

            HITitle titleYaxis1 = new HITitle();
            HICSSObject titleStyle1 = new HICSSObject();
            titleYaxis1.setStyle(titleStyle1);
            titleYaxis1.setRotation(270);
            titleYaxis1.setText("temperature (°F)");
//            titleYaxis1.setText("");
            yaxisOpposite.setTitle(titleYaxis1);
            yaxisOpposite.setOpposite(true);

            options.setYAxis(new ArrayList<>(Arrays.asList(yaxis, yaxisOpposite)));

            HILegend legend = new HILegend();
            legend.setEnabled(false);
            options.setLegend(legend);

            HITooltip tooltip = new HITooltip();
//            tooltip.setPointFormat("{series.name} <b>{point.y}</b><br/>");
            tooltip.setPointFormat("kWh: <b>{point.y}</b><br/>");
            tooltip.setHeaderFormat("Date: {point.x}<br/>");
            options.setTooltip(tooltip);
//            tooltip.setEnabled(false);

            HIPlotOptions plotoptions = new HIPlotOptions();
            plotoptions.setColumn(new HIColumn());
            plotoptions.getColumn().setStacking("normal");
            plotoptions.getColumn().setPointWidth(20);
            plotoptions.getColumn().setColorByPoint(true);

            options.setPlotOptions(plotoptions);+

            HISpline tempSpline = new HISpline();
            tempSpline.setName("Temp:");
            tempSpline.setData(new ArrayList<>(tempList));
            tempSpline.setTooltip(new HITooltip());
            tempSpline.setColor(HIColor.initWithName(strColorTemp));
            tempSpline.setYAxis(1);
            tempSpline.setTooltip(new HITooltip());
            tempSpline.getTooltip().setValueSuffix("°F");

            HISpline humiditySpline = new HISpline();
            humiditySpline.setName("Humidity:");
            humiditySpline.setData(new ArrayList<>(humidityList));
            humiditySpline.setTooltip(new HITooltip());
            humiditySpline.setColor(HIColor.initWithName(strColorHumidity));
            humiditySpline.setYAxis(1);
            humiditySpline.setTooltip(new HITooltip());
            humiditySpline.getTooltip().setValueSuffix("°F");

            HISpline heatSpline = new HISpline();
            heatSpline.setName("Humidity:");
            heatSpline.setData(new ArrayList<>(humidityList));
            heatSpline.setTooltip(new HITooltip());
            heatSpline.setColor(HIColor.initWithName(strColorHeat));
            heatSpline.setYAxis(1);
            heatSpline.setTooltip(new HITooltip());
            heatSpline.getTooltip().setValueSuffix("°F");

            HISpline windSpline = new HISpline();
            windSpline.setName("Humidity:");
            windSpline.setData(new ArrayList<>(humidityList));
            windSpline.setTooltip(new HITooltip());
            windSpline.setColor(HIColor.initWithName(strColorWind));
            windSpline.setYAxis(1);
            windSpline.setTooltip(new HITooltip());
            windSpline.getTooltip().setValueSuffix("°F");

            HIColumn column1 = new HIColumn();

            if (type == GraphType.NULL) {
                column1.setName("");
                tempSpline.setData(new ArrayList<>());
                humiditySpline.setData(new ArrayList<>());
                column1.setData(new ArrayList<>());
            } else {
                column1.setData(new ArrayList<>(usageList));
            }

            ArrayList seriesList = new ArrayList();
            if (usageList.size() != 0) {
                seriesList.add(column1);

                if (showLegendTemp)
                    seriesList.add(tempSpline);

                if (showLegendHumidity)
                    seriesList.add(humiditySpline);

                if (showLegendHeat)
                    seriesList.add(heatSpline);

                if (showLegendWind)
                    seriesList.add(windSpline);
            }

            cardViewKwh.setCardBackgroundColor(Color.parseColor(strColorKwh));

            if (showLegendTemp)
                cardViewTemp.setCardBackgroundColor(Color.parseColor(strColorTemp));
            else
                cardViewTemp.setCardBackgroundColor(Color.parseColor(strColorUnSelect));

            if (showLegendHumidity)
                cardViewHumidity.setCardBackgroundColor(Color.parseColor(strColorHumidity));
            else
                cardViewHumidity.setCardBackgroundColor(Color.parseColor(strColorUnSelect));

            if (showLegendHeat)
                cardViewHeat.setCardBackgroundColor(Color.parseColor(strColorHeat));
            else
                cardViewHeat.setCardBackgroundColor(Color.parseColor(strColorUnSelect));

            if (showLegendWind)
                cardViewWind.setCardBackgroundColor(Color.parseColor(strColorWind));
            else
                cardViewWind.setCardBackgroundColor(Color.parseColor(strColorUnSelect));

            options.setSeries(seriesList);

            chartView.setOptions(options);
            chartView.reload();
            chartView.redraw();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
MikolajMichalczak commented 2 months ago

Hi @Venkataramana0801!

Do you see any errors in logcat when running this code? Is the chart completely blank or are the axes visible?

You don't need to use reload and redraw in this case; just chartView.setOptions(options); is sufficient.

I changed your loop, where you fill the lists, to use random floats, because I don't have access to your specifica data. I also used a placeholder string for dateFormatList:

for (int i = 0; i < 100; i++) {
    dateFormatList.add("dateFormat");

    usageList.add(random.nextFloat() * 100);
    tempList.add(random.nextFloat() * 100);
    humidityList.add(random.nextFloat() * 100);
    heatIndexList.add(random.nextFloat() * 100);
    windSpeedList.add(random.nextFloat() * 100);
}

The code is working fine, so it means that your data list could be invalid at some point. Please try to debug its values or share a small sample if you can, so I can test it on my side with your data.

Venkataramana0801 commented 2 months ago

@MikolajMichalczak Thanks for you response, as you said I did sample graph and the sample graph code added in the method, the below is the method

private void setupSampleGraph() {
        Log.e("calling ", "@@@ setupSampleGraph");
        HIOptions optionsTest = new HIOptions();

        HIChart chartTest = new HIChart();
        chartTest.setType("column");
        optionsTest.setChart(chartTest);

        HITitle titleTest = new HITitle();
        titleTest.setText("Demo chart");

        optionsTest.setTitle(titleTest);

        HIColumn seriesTest = new HIColumn();
        seriesTest.setData(new ArrayList<>(Arrays.asList(49.9, 71.5, 106.4, 129.2, 144, 176, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4)));
        optionsTest.setSeries(new ArrayList<HISeries>(Collections.singletonList(seriesTest)));

        chartView.setOptions(optionsTest);
    }

And if I run this method in onCreateView method in the fragment, the graph is loading fine, the following is that method

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        layout_view = inflater.inflate(R.layout.fragment_usage_test_interval, container, false);
        chartView = layout_view.findViewById(R.id.hc);

     //   new UsagegraphServ(getActivity(), new String[]{"07/29/2024"}, "Get60minIntervalUsageData").execute();
        setupSampleGraph();

        return layout_view;
    }

But if I run the same method in onPostExecute of AsyncTask, the graph is not loading, it is displaying blank only, the following is the onPostExecute of AsyncTask.

    protected void onPostExecute(Integer i) {
        if (pgrsDialog.isShowing())
            pgrsDialog.dismiss();

        setupSampleGraph();

    }

I have verified in the logcat, there is no error displaying, here what is the issue with AsyncTask class. And also I am using the latest gradle dependencies
implementation 'com.github.highcharts:highcharts-android:11.4.6'

MikolajMichalczak commented 1 month ago

@Venkataramana0801 First of all, according to the documentation AsyncTask has been deprecated due to several issues, some of which may align with the problems you encountered:

AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes. It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground, and does not provide much utility over using Executors directly.

Given these issues, we cannot guarantee that Highcharts will always function correctly with AsyncTask.

However, I implemented a chart with AsyncTask and saw a console message: HIOptions not attached. Chart won't render without options.. Since Highcharts is a JavaScript-based framework, synchronization issues can arise. The best approach is to load all chart options before starting the async task with an empty series. Then, in the callback, update the options and series by creating a new list with your data and setting the series again.

Alternatively, another workaround that worked for me was to call chartView.setWillNotDraw(true) in the onCreateView method (before executing async task) and then call chartView.setWillNotDraw(false) after setupSampleGraph() in the onPostExecute() method (or at the end of setupSampleGraph() function).

Venkataramana0801 commented 1 month ago

Thank you for your quick response. It is working fine as per your these two lines, chartView.setWillNotDraw(true) and chartView.setWillNotDraw(false).