问题
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.
回答1:
It could be, that you sort the data the wrong way. Try to use a bubblesort to fix is problem. The frist value in the data array (position 0) have to be the object with the lowest timestamp.
If you get the data from a DB an sort the values DESC to get the lastet onces the chronological order is wrong and you have to sort the array before you can use it for the graphview with timestamps at the x-axis.
I hope this is the problem and my answer will help you.
来源:https://stackoverflow.com/questions/17219391/android-graphview-all-x-axis-values-are-set-to-the-latest-value