I'm trying to make a graph in real time, but I get a java.util.ConcurrentModificationException error. If you set a high delay thread.sleep(500), then the chart will fill correctly, but if you set thread.sleep(100) or less, you always get an error after drawing 200-400 points, in total there are 2000 points in the chart
I create a graph in doInBackground()
Code:
public class MainActivity extends AppCompatActivity {
private final String ecgData = "ecg2.json";
private Button bt_graph_zoom;
private GraphView graph;
class GraphCreator extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... strings) {
String json = null;
try {
InputStream inputStream = getAssets().open(strings[0]);
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
json = new String(data, StandardCharsets.UTF_8);
JSONObject jsonObject = new JSONObject(json);
JSONArray jsonArray = jsonObject.getJSONArray("ecg");
LineGraphSeries<DataPoint> series = new LineGraphSeries<>();
graph.addSeries(series);
series.setTitle("Зашумленный сигнал ЭКГ");
series.setAnimated(true);
for (int i = 0; i < 2000; i++) {
Thread.sleep(50);
JSONObject obj = jsonArray.getJSONObject(i);
series.appendData(new DataPoint(i,obj.getDouble("y")),false,2000);
}
} catch (IOException | JSONException | InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
graph = findViewById(R.id.graph);
graph.setTitle("Исходный сигнал ЭКГ");
graph.setTitleTextSize(55);
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().calcCompleteRange();
graph.getViewport().setMinY(-1);
graph.getViewport().setMaxY(1.6);
graph.getLegendRenderer().setVisible(true);
graph.getLegendRenderer().setAlign(LegendRenderer.LegendAlign.TOP);
graph.getGridLabelRenderer().setHorizontalAxisTitle("Отсчеты");
graph.getGridLabelRenderer().setVerticalAxisTitle("Напряжение (мВ)");
graph.getGridLabelRenderer().setHorizontalAxisTitleTextSize(55);
graph.getGridLabelRenderer().setVerticalAxisTitleTextSize(55);
graph.getGridLabelRenderer().setPadding(60);
bt_graph_zoom = findViewById(R.id.bt_graph_zoom);
bt_graph_zoom.setOnClickListener(view -> graph.getViewport().setScalable(!graph.getViewport().isScalable()));
new GraphCreator().execute(ecgData);
}
Full stack trace
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.holterapp, PID: 1773
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.jjoe64.graphview.series.BaseSeries$1.next(BaseSeries.java:237)
at com.jjoe64.graphview.series.BaseSeries$1.next(BaseSeries.java:187)
at com.jjoe64.graphview.series.LineGraphSeries.draw(LineGraphSeries.java:263)
at com.jjoe64.graphview.GraphView.drawGraphElements(GraphView.java:309)
at com.jjoe64.graphview.GraphView.onDraw(GraphView.java:336)
at android.view.View.draw(View.java:22350)
at android.view.View.updateDisplayListIfDirty(View.java:21226)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4500)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4473)
at android.view.View.updateDisplayListIfDirty(View.java:21186)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:559)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:565)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:642)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4101)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3828)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3099)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:731)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)