-
Notifications
You must be signed in to change notification settings - Fork 369
Chart data update
Sometimes in real-world project charts need to be updated with the new data. There's no need to recreate the chart to achieve that. This approach is very slow and leads to the complete redraw of the chart. The best practice is to apply the new data to the existing chart. In this case, the chart will redraw the required elements automatically, for example, data series only. But the rest of the chart elements will remain the same. It works very fast and meets requirements of the realtime update purposes.
The exact implementation depends on the chart type and the way the data was applied to the chart initially. There are three available options.
Some chart types support only one series of data and it can be applied to the chart instance directly without creating data sets and mappings. For example, the Pie Chart.
The Pie Chart can be created with the following line (step 1):
final Pie pie = AnyChart.pie();
Then create a DataEntry List and populate it with data (step 2):
List<DataEntry> data = new ArrayList<>();
data.add(new ValueDataEntry("Apples", 6371664));
data.add(new ValueDataEntry("Pears", 789622));
data.add(new ValueDataEntry("Bananas", 7216301));
data.add(new ValueDataEntry("Grapes", 1486621));
data.add(new ValueDataEntry("Oranges", 1200000));
Finally, apply the data to the chart instance directly like this (step 3):
pie.data(data);
To update the created Pie Chart you need to create new DataEntry List, populate it with the data and simply apply it to the existing chart. In other words, repeat steps 2 and 3. As you can see, there's no need to replace or recreate the chart.
Below you can find the snippet that demonstrates how it works. For demonstration purposes, we use a loop and random values to simulate real-time updates.
// create chart
final Pie pie = AnyChart.pie();
// create data List
List<DataEntry> data = new ArrayList<>();
data.add(new ValueDataEntry("Apples", 6371664));
data.add(new ValueDataEntry("Pears", 789622));
data.add(new ValueDataEntry("Bananas", 7216301));
data.add(new ValueDataEntry("Grapes", 1486621));
data.add(new ValueDataEntry("Oranges", 1200000));
// apply data to the chart
pie.data(data);
// render the chart
AnyChartView anyChartView = (AnyChartView) findViewById(R.id.any_chart_view);
anyChartView.setChart(pie);
// simulate real-time updates
final int delayMillis = 500;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
public void run() {
// create new data List and populate it with values
List<DataEntry> data = new ArrayList<>();
data.add(new ValueDataEntry("Apples", new Random().nextDouble() * 140d));
data.add(new ValueDataEntry("Pears", new Random().nextDouble() * 140d));
// apply the new List to the existing chart
pie.data(data);
handler.postDelayed(this, delayMillis);
}
};
handler.postDelayed(runnable, delayMillis);
Most of the chart types support multiple series for the same chart. But sometimes it is required to show only one series. In this case, usually, the data is applied to the series instance without creating data sets and mappings. The main idea remains the same. Let's take the example of the Line Chart with a single series.
Create the Line chart (step 1):
Cartesian cartesian = AnyChart.line();
Then create a DataEntry List and populate it with data (step 2):
List<DataEntry> seriesData = new ArrayList<>();
seriesData.add(new ValueDataEntry("A", 5));
seriesData.add(new ValueDataEntry("B", 4));
seriesData.add(new ValueDataEntry("C", 3));
seriesData.add(new ValueDataEntry("D", 4));
Create a line series and apply the data to its constructor (step 3):
Line series1 = cartesian.line(seriesData);
To update the Line series data you need to create a new DataEntry List and apply the data to the existing series using the data()
method. For details, check the full code snippet below.
AnyChartView anyChartView = findViewById(R.id.any_chart_view);
// create Line chart
Cartesian cartesian = AnyChart.line();
// create data List
List<DataEntry> seriesData = new ArrayList<>();
seriesData.add(new ValueDataEntry("A", 5));
seriesData.add(new ValueDataEntry("B", 4));
seriesData.add(new ValueDataEntry("C", 3));
seriesData.add(new ValueDataEntry("D", 4));
// create Line series
final Line series1 = cartesian.line(seriesData);
anyChartView.setChart(cartesian);
// simulate real-time update
final int delayMillis = 500;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
public void run() {
// create new data List
List<DataEntry> data = new ArrayList<>();
data.add(new ValueDataEntry("A", new Random().nextDouble() * 10));
data.add(new ValueDataEntry("B", new Random().nextDouble() * 10));
data.add(new ValueDataEntry("C", new Random().nextDouble() * 10));
data.add(new ValueDataEntry("D", new Random().nextDouble() * 10));
// apply new data to the series
series1.data(data);
handler.postDelayed(this, delayMillis);
}
};
handler.postDelayed(runnable, delayMillis);
Using data sets and mapping is very useful for working with multiple series. For example, a Line chart with three Line series. In this case, the data for all series can be stored in a single data set. And then applied to every series by individual mappings. For demonstration we will use an already known Line chart.
Create a Line chart (step 1):
Cartesian cartesian = AnyChart.line();
Create a data List that includes data for three series. For this purpose, you can create custom data entry. The full code of this approach will be available at the end of the article (step 2):
List<DataEntry> seriesData = new ArrayList<>();
seriesData.add(new CustomDataEntry("2006", 16.6, 20.3, 11.5));
seriesData.add(new CustomDataEntry("2007", 14.1, 20.7, 12.2));
seriesData.add(new CustomDataEntry("2008", 15.7, 21.6, 10));
seriesData.add(new CustomDataEntry("2009", 12.0, 22.5, 8.9));
Declare a data set, apply the data to it, and create mappings for every series (step 3):
final Set set = Set.instantiate();
set.data(seriesData);
Mapping series1Mapping = set.mapAs("{ x: 'x', value: 'value' }");
Mapping series2Mapping = set.mapAs("{ x: 'x', value: 'value2' }");
Mapping series3Mapping = set.mapAs("{ x: 'x', value: 'value3' }");
Create three line series and apply mappings (step4):
Line series1 = cartesian.line(series1Mapping);
Line series2 = cartesian.line(series2Mapping);
Line series3 = cartesian.line(series3Mapping);
To update all three series data create new DataEntry List and apply it to the existing data set. There's no need to recreate mappings or series. The full snippet is below.
AnyChartView anyChartView = findViewById(R.id.any_chart_view);
// create Line Chart
Cartesian cartesian = AnyChart.line();
// create data List
List<DataEntry> seriesData = new ArrayList<>();
seriesData.add(new CustomDataEntry("2006", 16.6, 20.3, 11.5));
seriesData.add(new CustomDataEntry("2007", 14.1, 20.7, 12.2));
seriesData.add(new CustomDataEntry("2008", 15.7, 21.6, 10));
seriesData.add(new CustomDataEntry("2009", 12.0, 22.5, 8.9));
// declare data set
final Set set = Set.instantiate();
// apply data to the data set
set.data(seriesData);
// create mappings for every series
Mapping series1Mapping = set.mapAs("{ x: 'x', value: 'value' }");
Mapping series2Mapping = set.mapAs("{ x: 'x', value: 'value2' }");
Mapping series3Mapping = set.mapAs("{ x: 'x', value: 'value3' }");
// create three series
Line series1 = cartesian.line(series1Mapping);
Line series2 = cartesian.line(series2Mapping);
Line series3 = cartesian.line(series3Mapping);
cartesian.legend().enabled(true);
anyChartView.setChart(cartesian);
// simulate real-time update
final int delayMillis = 500;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
public void run() {
// create new List
List<DataEntry> data = new ArrayList<>();
data.add(new CustomDataEntry("2006", new Random().nextDouble() * 20, new Random().nextDouble() * 20, new Random().nextDouble() * 20));
data.add(new CustomDataEntry("2007", new Random().nextDouble() * 20, new Random().nextDouble() * 20, new Random().nextDouble() * 20));
data.add(new CustomDataEntry("2008", new Random().nextDouble() * 20, new Random().nextDouble() * 20, new Random().nextDouble() * 20));
data.add(new CustomDataEntry("2009", new Random().nextDouble() * 20, new Random().nextDouble() * 20, new Random().nextDouble() * 20));
// apply new data to existing data set
set.data(data);
handler.postDelayed(this, delayMillis);
}
};
handler.postDelayed(runnable, delayMillis);