PhilJay / MPAndroidChart

A powerful 🚀 Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, panning and animations.
Other
37.6k stars 9.02k forks source link

Performance with lot of values #1245

Closed dihcar76 closed 8 years ago

dihcar76 commented 8 years ago

Hello, I am trying to use MPAndroidChart library to create a realtime linechart, It takes a value every 10 millisecond, In a simple example it is very fluid but in my case it just doesn't work. Have you an idea ? I've got one: simply remove first element of data each time not to redraw all line chart. But I need to save it all another way in an ArrayList to redraw it again. Is it a simple way not to draw all chart? Here is what I am doing:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d("EEGFragment", "onCreateView");
    View rootView = inflater.inflate(R.layout.fragment_graph_sectionmp, container, false);
//        EEGPlot = setGraph(getString(R.string.eeg_range), getString(R.string.graph_domain),
//                EEGHistorySeries, (XYPlot) rootView.findViewById(R.id.graph), 255, 255, 255);
    LinearLayout touchView = (LinearLayout) rootView.findViewById(R.id.graphLayoutmp);

    mChart = (LineChart) rootView.findViewById(R.id.graphmp);
    mChart.setDescription("");
    mChart.setNoDataTextDescription("pas de données");
    mChart.setHighlightPerTapEnabled(false);
    mChart.setTouchEnabled(true);
    mChart.setDragEnabled(true);
    mChart.setScaleEnabled(true);
    mChart.setDrawGridBackground(true);
    mChart.setPinchZoom(true);
    mChart.setBackgroundColor(Color.LTGRAY);
    data.setValueTextColor(Color.WHITE);
    mChart.getAxisLeft().setStartAtZero(false); //Set to not start at 0
    mChart.setData(data);
    Legend l = mChart.getLegend();
    l.setForm(Legend.LegendForm.LINE);
    l.setTextColor(Color.WHITE);
    XAxis xl = mChart.getXAxis();
    xl.setTextColor(Color.WHITE);
    xl.setPosition(XAxis.XAxisPosition.BOTTOM);
    xl.setDrawGridLines(true);
    xl.setAvoidFirstLastClipping(true);
    YAxis yl = mChart.getAxisLeft();
    yl.setTextColor(Color.WHITE);
    yl.setAxisMaxValue(20f);
    yl.setDrawGridLines(true);
    YAxis yl2 = mChart.getAxisRight();
    yl2.setEnabled(false);
    mChart.enableScroll();
    final GestureDetectorCompat gestureDetector = new GestureDetectorCompat(
            getActivity(), new GesturesDetectorListener2(new WeakReference<>(mChart),
            getActivity(), new WeakReference<>(container), BOUND_RANGE, concurrentSkipListMap));
    touchView.findViewById(R.id.graphmp).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    });

    return rootView;
}

private void addEntry(float yVals, int xVals) {
    data = mChart.getData();
    if (data != null) {
        set = data.getDataSetByIndex(0);
        if (set == null) {
            set = createSet();
            data.addDataSet(set);
        }
        data.addXValue(set.getEntryCount() + "");
        data.addEntry(new Entry(yVals, xVals), 0);
        mChart.notifyDataSetChanged();
        mChart.setVisibleXRange(0, 100);//limit number of visible entries
        mChart.moveViewToX(data.getXValCount() - 101);//scroll to last entries
        //data.removeEntry(data.getXValCount()-101,0);
    }

}

private LineDataSet createSet() {
    LineDataSet set = new LineDataSet(null, "EEG test");
    set.setDrawCubic(true);
    set.setCubicIntensity(0.2f);
    set.setAxisDependency(YAxis.AxisDependency.LEFT);
    set.setColor(ColorTemplate.getHoloBlue());
    set.setCircleColor(ColorTemplate.getHoloBlue());
    set.setLineWidth(2f);
    set.setCircleSize(4f);
    set.setFillAlpha(65);
    set.setFillColor(ColorTemplate.getHoloBlue());
    set.setHighLightColor(Color.rgb(244, 117, 117));
    set.setValueTextColor(Color.WHITE);
    set.setValueTextSize(10f);
    return set;
}

/**
 * Add a measure to the plot and keep it in the treeMap
 *
 * @param currentMeasure the measure to add
 */
public void drawEEG(final Measure currentMeasure) {//final added
    if (getActivity() != null && isAdded()) {
        if (currentMeasure != null) {
            // if new point out of bound and user not scrolling the plot
            // move boundaries to take in account the new point
            if ((time > lowerBound + BOUND_RANGE)
                    && !((GraphActivity) getActivity()).isFullScreen()) {
                lowerBound += 1;
//                    EEGPlot.setDomainBoundaries(lowerBound, lowerBound + BOUND_RANGE, BoundaryMode.FIXED);
//                    if (EEGHistorySeries.size() == BOUND_RANGE) {
//                        EEGHistorySeries.removeFirst();
//                    }
            }
//                EEGHistorySeries.addLast(time, currentMeasure.getDataReceived());
            concurrentSkipListMap.put(time, currentMeasure.getDataReceived());
            //time++;
        }
        if (isVisible() && !((GraphActivity) getActivity()).isFullScreen()) {//&& time % 100 == 0
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
//                        EEGPlot.redraw();
                    addEntry(currentMeasure.getDataReceived().floatValue(),time++ );//final currentMeasure added TODO perte d'information conversion long en int currentMeasure.getMeasureTimestamp().intValue()
                }
            });
        }
    } else {
        Log.e("drawEEG", "MESSAGE IGNORED !!!");
    }
}
PhilJay commented 8 years ago

Well a LineChart with optimal performance settings (no circles, no cubic) will render about 20.000 data points smoothly on an average device resulting in about 50ms draw time per refresh.

So as long as you have optimal performance settings and not more than ~4.000 data points (ratio 50:10ms vs 20:4k points) adding data should not lag.

dihcar76 commented 8 years ago

Hi,

because I have got more values, I am trying to display only few neccessary set of values fitting the screen of the tablet (and so by deleting others outside the screen). Is there a way in a onChartGestureStart to get the offset in xaxis of the motion? thanks

2015-12-04 15:34 GMT+01:00 Philipp Jahoda notifications@github.com:

Well a LineChart with optimal performance settings (no circles, no cubic) will render about 20.000 data points smoothly on an average device resulting in about 50ms draw time per refresh.

So as long as you have optimal performance settings and not more than ~4.000 data points (ratio 50:10ms vs 20:4k points) it should render pretty smoothly.

— Reply to this email directly or view it on GitHub https://github.com/PhilJay/MPAndroidChart/issues/1245#issuecomment-161981174 .

dihcar76 commented 8 years ago

hi,

have you got an idea on how can I do this to scroll after searching in databases for xvals interval? thanks

2015-12-05 22:45 GMT+01:00 Rachid Bougrine bougrinerachid@gmail.com:

Hi,

because I have got more values, I am trying to display only few neccessary set of values fitting the screen of the tablet (and so by deleting others outside the screen). Is there a way in a onChartGestureStart to get the offset in xaxis of the motion? thanks

2015-12-04 15:34 GMT+01:00 Philipp Jahoda notifications@github.com:

Well a LineChart with optimal performance settings (no circles, no cubic) will render about 20.000 data points smoothly on an average device resulting in about 50ms draw time per refresh.

So as long as you have optimal performance settings and not more than ~4.000 data points (ratio 50:10ms vs 20:4k points) it should render pretty smoothly.

— Reply to this email directly or view it on GitHub https://github.com/PhilJay/MPAndroidChart/issues/1245#issuecomment-161981174 .