I've created a real-time graph, where the values of the x-axis are set to show the time at which the corresponding y-axis values were generated. The graph is constantly updated. The value send to the graph is time in milliseconds. I've created a function which produces the time string in different ways, depending on the time. Here's the code:
GraphView heartRateGraph = new LineGraphView(this, "Heart-rate") {
@Override
protected String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return getTime((long) value);
} else {
return super.formatLabel(value, isValueX);
}
}
};
private String getTime(long milliSeconds) {
String dateFormat;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
if(minute == 59 && second >= 57){
dateFormat = "HH:mm:ss";
}else{
dateFormat = "mm:ss";
}
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
return formatter.format(calendar.getTime());
}
The problem is that all x-axis values are set to the latest one, causing the graph to show nothing but a flat line. Any help would be greatly appriciated.
Here is the code requested by jjoe64:
I use Threads to create the graphs and fill them with data.
The code for creating the graphs using threads:
RTGKcalThread = new RealTimeGraphKcalThread(activity,
graphConstructor.getBarGraph(), monitor);
RTHRThread = new RealTimeGraphHRValueThread(activity,
graphConstructor.getlineGraph());
The relevant code in the GraphConstructor class:
public void initializeGraphs() {
initializeGraphsDisplayDimensions();
barGraphView = new BarGraphView(activity, "Calories expendeture(Kcal)"){
@Override
protected String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return getTime((long) value);
} else {
return super.formatLabel(value, isValueX);
}
}
};
lineGraphView = new LineGraphView(activity, "Heart-rate"){
@Override
protected String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return getTime((long) value);
} else {
return super.formatLabel(value, isValueX);
}
}
};
setUpGraph(barGraphView, 0);
setUpGraph(lineGraphView, 1);
}
private void setUpGraph(GraphView graphView, int index){
graphView.setViewPort(1, 4);
graphView.setScrollable(true);
if(displayHeight <= 854){
graphView.getGraphViewStyle().setVerticalLabelsFontSize(18f);
graphView.getGraphViewStyle().setHorizontalLabelsFontSize(18f);
}
else if(displayHeight > 854){
graphView.getGraphViewStyle().setVerticalLabelsFontSize(24f);
graphView.getGraphViewStyle().setHorizontalLabelsFontSize(24f);
}
layouts.get(index).addView(graphView);
}
public GraphView getBarGraph(){
return barGraphView;
}
public GraphView getlineGraph(){
return lineGraphView;
}
RealTimeGraphKcalThread and RealTimeGraphHRValueThread extend the realTimeGraphThread. This is where the series are created and data appended.
public abstract class RealTimeGraphThread extends TerminateableThread {
private GraphViewSeries series;
private boolean running = true;
private Activity activity;
private int delay;
protected abstract double getValue();
protected RealTimeGraphThread(Activity activity, GraphView graphView,
int delay) {
series = new GraphViewSeries(new GraphViewData[] {});
graphView.addSeries(series);
this.activity = activity;
this.delay = delay;
}
@Override
public void run() {
long timer, diff;
timer = System.currentTimeMillis();
while (running) {
double value = getValue();
if (String.valueOf(value) != null) {
activity.runOnUiThread(new UpdateValue((double) System
.currentTimeMillis(), value));
}
timer += delay;
diff = timer - System.currentTimeMillis();
if (diff > 0)
try {
sleep(diff);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
@Override
public void terminate() {
running = false;
}
private void resetSeries() {
GraphViewData[] newData = new GraphViewData[10];
int j = 0;
for (int i = series.getSize() - 10; i < series.getSize(); i++) {
newData[j] = series.getValues()[i];
j++;
}
series.resetData(newData);
}
private class UpdateValue implements Runnable {
private double timeStamp, value;
public UpdateValue(double timeStamp, double value) {
this.timeStamp = timeStamp;
this.value = value;
}
@Override
public void run() {
series.appendData(new GraphViewData(timeStamp, value), true);
if (series.getSize() >= 300) {
resetSeries();
}
}
}
EDIT:
If I change the following:
while (running) {
double value = getValue();
if (String.valueOf(value) != null) {
activity.runOnUiThread(new UpdateValue((double) System
.currentTimeMillis(), value));
}
timer += delay;
diff = timer - System.currentTimeMillis();
if (diff > 0)
try {
sleep(diff);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
to
double i = 1d;
while (running) {
double value = getValue();
if (String.valueOf(value) != null) {
activity.runOnUiThread(new UpdateValue(i, value));
}
timer += delay;
diff = timer - System.currentTimeMillis();
if (diff > 0){
try {
sleep(diff);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
i++;
}
and
@Override
protected String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return getTime((long) value);
to
@Override
protected String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return getTime(System.CurrentTimeMillis());
I get a working graph, but all the x-axis values are still set to the latest one.