Java – Bar charts are slow to draw in AChartEngine

Bar charts are slow to draw in AChartEngine… here is a solution to the problem.

Bar charts are slow to draw in AChartEngine

I’m developing an Android app and using AChartEngine as a charting library. I hope that when drawing a bar chart, it draws slowly so that it gives us the look and feel that it is being drawn with some kind of animation. How do I achieve this behavior?

   values.add(0, InCycleDuration);
    values.add(1, UnknownDowntimeDuration);
    int[] colors = new int[EqSDLenght] ;
     colors[0] = Color.parseColor("#008000");
    colors[1] = Color.parseColor("#FFFF00");

for(int j = EqSDLenght - 1 ; j >= 0; j--)
              {

if(EquipmentRKey[j].equals("EquipmentStatusTypeName.UnknownDowntime"))
                 {

titles [j] =  "Unknown Downtime" ;

}

if(EquipmentRKey[j].equals("EquipmentStatusTypeName.InCycle"))
                 {

titles [j] =  "In Cycle" ;
                 }
               }

renderer = buildBarRenderer(colors);
            setChartSettings(renderer, "Comparison Chart", "", "Total Time Consumed", 0,
                6, 0, 100, Color.DKGRAY, Color.DKGRAY);
            for(int i=0 ; i < titles.length; i++)
            {
                x.add(new double[]{ 1,2,3,4,5});
            }

for(int i=0; i<name.length; i++)
            {
                renderer.addTextLabel(i+1, name[i]);

}

renderer.setXLabels(0);

renderer.setLabelsTextSize(12);

renderer.getSeriesRendererAt(0).setDisplayChartValues(false);
            renderer.getSeriesRendererAt(1).setDisplayChartValues(false);
            renderer.setShowGridX(true);
            renderer.setGridColor(Color.parseColor("#359ACD32"));
            final int orientation = this.getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_PORTRAIT)   
            {
            renderer.setYLabels(11);
            }
            if (orientation == Configuration.ORIENTATION_LANDSCAPE)   
            {
            renderer.setYLabels(6);
            }
            renderer.setXLabelsAlign(Align.CENTER);
            renderer.setYLabelsAlign(Align.CENTER);
            renderer.setXLabelsColor(Color.DKGRAY);
            renderer.setYLabelsColor(0, Color.DKGRAY); 
            renderer.setPanEnabled(false, false);
            renderer.setZoomRate(1.1f);
            renderer.setBarSpacing(0.8f);
            renderer.setMargins( new int []{55, 40, 35, 30});
            renderer.setApplyBackgroundColor(true);

renderer.setBackgroundColor(Color.WHITE);
            renderer.setMarginsColor(Color.WHITE);    
            renderer.setLegendHeight(40);

renderer.setChartTitleTextSize(30);
            renderer.getXTextLabelLocations();
            renderer.setClickEnabled(true);

mChartView =  ChartFactory.getBarChartView(SalesBar.this, buildBarDataset(titles, values), renderer,
                org.achartengine.chart.BarChart.Type.STACKED);

layout.addView(mChartView, LayoutParams.FILL_PARENT , LayoutParams.FILL_PARENT);
             renderer.setSelectableBuffer(100);

mChartView.setOnTouchListener(new OnTouchListener() {

public boolean onTouch(View v, MotionEvent event) {
                         if (MotionEvent.ACTION_DOWN == event.getAction()) {
                            xaxis =  event.getRawX();
                                yaxis =  event.getRawY(); 
                              xx = (int) xaxis;
                            yy = (int) yaxis;
                        } else if (MotionEvent.ACTION_UP == event.getAction()) {
                            xaxis =  event.getX();
                              yaxis =  event.getY(); 
                              xx = (int) xaxis;
                            yy = (int) yaxis;
                        }
                        else{}

return false;
                    }
                });

mChartView.setOnClickListener(new View.OnClickListener() {
                 Toast test;
                public void onClick(View v) {
                  SeriesSelection seriesSelection = mChartView.getCurrentSeriesAndPoint();

if (seriesSelection != null) {

int status_index = seriesSelection.getSeriesIndex();
                      int equipment_index = seriesSelection.getPointIndex();
                      double duration_value = seriesSelection.getValue();

if(status_index == 0)
                      {
                          if(equipment_index == 0)
                          {
                              duration_value = EquipmentHoursDuration[0][1];
                          }
                          if(equipment_index == 1)
                          {
                              duration_value = EquipmentHoursDuration[1][1];
                          }
                          if(equipment_index == 2)
                          {
                              duration_value = EquipmentHoursDuration[2][1];
                          }
                          if(equipment_index == 3)
                          {
                              duration_value = EquipmentHoursDuration[3][1];
                          }
                          if(equipment_index == 4)
                          {
                              duration_value = EquipmentHoursDuration[4][1];
                          }
                          String final_status = titles[status_index];
                         String final_equipment = EquipmentNamePartial[equipment_index];
                        test = Toast.makeText(
                                SalesBar.this,
                                  "Status: " + final_status + '\n'
                                + "Equipment: " + final_equipment + '\n'
                                + "Duration: " + duration_value + " hours", Toast.LENGTH_SHORT);
                       ((TextView)((LinearLayout)test.getView()).getChildAt(0))
                      .setGravity(Gravity.LEFT);

test.setGravity(Gravity.TOP| Gravity.LEFT, xx, yy);

test.show();
                      }

else
                      {
                     String final_status = titles[status_index];
                     String final_equipment = EquipmentNamePartial[equipment_index];
                     if(equipment_index == 0)
                  {
                      duration_value = EquipmentHoursDuration[0][0];
                  }
                  if(equipment_index == 1)
                  {
                      duration_value = EquipmentHoursDuration[1][0];
                  }
                  if(equipment_index == 2)
                  {
                      duration_value = EquipmentHoursDuration[2][0];
                  }
                  if(equipment_index == 3)
                  {
                      duration_value = EquipmentHoursDuration[3][0];
                  }
                  if(equipment_index == 4)
                  {
                      duration_value = EquipmentHoursDuration[4][0];
                  }

test = Toast.makeText(
                            SalesBar.this,
                              "Status: " + final_status + '\n'
                            + "Equipment: " + final_equipment + '\n'
                            + "Duration: " + duration_value + " hours", Toast.LENGTH_SHORT);

test.setGravity(Gravity.TOP| Gravity.LEFT, xx, yy);
                        ((TextView)((LinearLayout)test.getView()).getChildAt(0))
                          .setGravity(Gravity.LEFT);

test.show();
                      }
                  }
                }
              });

protected XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
                XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
                renderer.setAxisTitleTextSize(16);
                renderer.setChartTitleTextSize(20);
                renderer.setLabelsTextSize(15);
                renderer.setLegendTextSize(15);
                int length = colors.length;
                for (int i = 0; i < length; i++) {
                  SimpleSeriesRenderer r = new SimpleSeriesRenderer();
                  r.setColor(colors[i]);
                  renderer.addSeriesRenderer(r);
                }
                return renderer;
              }

protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor, int labelsColor) {
                renderer.setChartTitle(title);
                renderer.setXTitle(xTitle);
                renderer.setYTitle(yTitle);
                renderer.setXAxisMin(xMin);
                renderer.setXAxisMax(xMax);
                renderer.setYAxisMin(yMin);
                renderer.setYAxisMax(yMax);
                renderer.setAxesColor(axesColor);
                renderer.setLabelsColor(labelsColor);
              }

protected XYMultipleSeriesDataset buildBarDataset(String[] titles, List<double[]> values) {
                XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
                int length = titles.length;
                for (int i = 0; i < length; i++) {
                  CategorySeries series = new CategorySeries(titles[i]);
                  double[] v = values.get(i);
                  int seriesLength = v.length;
                  for (int k = 0; k < seriesLength; k++) {
                    series.add(v[k]);
                  }
                  dataset.addSeries(series.toXYSeries());
                }

return dataset;
              }
}

Solution

You can display the initial View with some values, and then gradually change the values until they reach the final value. During this time, you will modify the dataset with the new values and call mChartView.repaint() in a separate thread that will indeed hibernate for around 100 milliseconds.

It should be as simple as this :

new Thread(new Runnable() {
  public void run() {
    while (!stopped) {
      try {
        Thread.sleep(100);
      } catch (Exception e) {
         ignore
      }
       modify the contents of your series here
      ...
      mChartView.repaint();
    }
  }
}).start();

Related Problems and Solutions