Pre loader

How to fix a lag when scrolling over a line chart that has already been drawn

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

0
0

Hi
I have a line chart that has already been drawn and synced with a sound.
when we play sound, chart begin to scroll horizontally.
but problem is lagging when scrolling chart.
Is there a way to fix this problem?

private Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        forceRunInPauseMode = false;

        getActivity().runOnUiThread(() -> {
            currentTime = (int) exoPlayer.getCurrentPosition();
            binding.tvCurrentDuration.setText(MiliToTimeConverter.milliToTime(currentTime));
        });

        int currentRange = currentTime * 2;


        if (!isDraw) {
            DoubleValues xValues = new DoubleValues(Arrays.copyOfRange(xDoubleArray, 0, xDoubleArray.length - 1));
            DoubleValues yValues = new DoubleValues(Arrays.copyOfRange(yDoubleArray, 0, yDoubleArray.length - 1));
            DoubleSeries doubleSeries = new DoubleSeries(xValues, yValues);
            lineData.append(doubleSeries.getxValues(), doubleSeries.getyValues());
            isDraw = true;
        }
        xVisibleRange.setMinMax(currentRange - visibleInterval / 2, currentRange + visibleInterval / 2);
    }
};

private void updateChart() {
    schedule = scheduledExecutorService.scheduleWithFixedDelay(() -> {
        if (!isPlaying && !forceRunInPauseMode)
            return;
        UpdateSuspender.using(binding.sciChart, mRunnable);
    }, 0, TIME_INTERVAL, TimeUnit.MILLISECONDS);
}


private void pause() {
    exoPlayer.setPlayWhenReady(false);
    binding.ivPlay.setImageResource(R.drawable.ic_play);
    if (schedule != null)
        schedule.cancel(false);
}

private void initSciChart() {

    isChartConfigured = true;
    SciChartBuilder.init(getContext());
    binding.sciChart.setBackgroundColor(getResources().getColor(R.color.colorTransparent));

    // Obtain the SciChartBuilder instance
    SciChartBuilder mSciChartBuilder = SciChartBuilder.instance();

    //set border style
    binding.sciChart.setRenderableSeriesAreaBorderStyle(null);

    xVisibleRange = new DoubleRange();

    // Create a numeric X axis
    final IAxis xAxis = mSciChartBuilder.newNumericAxis()
            .withVisibleRange(xVisibleRange)
            .withGrowBy(new DoubleRange(0.25d * visibleInterval / totalDuration, 0.25d * visibleInterval / totalDuration))
            .withAutoRangeMode(AutoRange.Never)
            .build();

    final IAxis yAxis = mSciChartBuilder.newNumericAxis()
            .withVisibleRange(-1d, 1d)
            .withAutoRangeMode(AutoRange.Never)
            .build();

    xAxis.setVisibleRangeChangeListener((iAxisCore, oldRange, newRange, isAnimating) -> {
        if (!isPlaying) {
            double c = ((newRange.getMinAsDouble() + newRange.getMaxAsDouble()) / 4);
            getActivity().runOnUiThread(() -> binding.tvCurrentDuration.setText(MiliToTimeConverter.milliToTime((long) c)));
        }
    });


    xAxis.setDrawMajorGridLines(false);
    xAxis.setDrawMinorGridLines(false);
    xAxis.setDrawMajorBands(false);
    xAxis.setDrawMajorTicks(true);
    xAxis.setDrawMinorTicks(true);
    xAxis.setTickProvider(new CustomTickProvider());
    xAxis.setMaxAutoTicks(MAX_AUTO_TICKS);
    xAxis.setMinorsPerMajor(MINOR_PER_MAJOR);
    xAxis.setVisibility(View.GONE);


    yAxis.setDrawMajorGridLines(false);
    yAxis.setDrawMinorGridLines(false);
    yAxis.setDrawMajorBands(false);
    yAxis.setDrawMajorTicks(false);
    yAxis.setDrawMinorTicks(false);
    yAxis.setTickProvider(new CustomTickProvider());
    yAxis.setMaxAutoTicks(MAX_AUTO_TICKS);
    yAxis.setMinorsPerMajor(MINOR_PER_MAJOR);
    yAxis.setVisibility(View.GONE);


    VerticalLineAnnotation verticalLine = mSciChartBuilder.newVerticalLineAnnotation()
            .withX1(0.5)   // black
            .withStroke(new SolidPenStyle(ColorUtil.argb(250, 120, 126, 136), true, 1f, null))
            .withCoordinateMode(AnnotationCoordinateMode.RelativeX)
            .build();

    ModifierGroup chartModifiers = mSciChartBuilder.newModifierGroup()
            .withModifier(new GestureModifierBase() {
                @Override
                public void detach() {
                    super.detach();
                }

                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                    return false;
                }

                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                    // Scroll X
                    xAxis.scroll((-distanceX/2), ClipMode.ClipAtExtents);

                    return true;
                }
            })
            .build();

    lineData = mSciChartBuilder.newXyDataSeries(Double.class, Double.class).build();
    XyDataSeries staticData = mSciChartBuilder.newXyDataSeries(Double.class, Double.class).build();

    final FastLineRenderableSeries lineSeries = mSciChartBuilder.newLineSeries()
            .withDataSeries(lineData)
            //.withPointMarker(mSciChartBuilder.newPointMarker(new EllipsePointMarker()).withSize(7, 7).withStroke(0xFF006400, 1).withFill(0xFFFFFFFF).build())
            .withPaletteProvider(new XYCustomPaletteProvider(ColorUtil.argb(255, 50, 153, 0))) // green
            .withStrokeStyle(ColorUtil.argb(250, 120, 126, 136), 1f, true) // black
            .build();

    final IRenderableSeries staticLineSeries = mSciChartBuilder.newLineSeries()
            .withDataSeries(staticData)
            .withPaletteProvider(new XYCustomPaletteProvider(ColorUtil.argb(255, 50, 153, 0))) // green
            .withStrokeStyle(ColorUtil.argb(250, 120, 126, 136), 1f, true) // black
            .build();

    DoubleValues xValues = new DoubleValues(Arrays.copyOfRange(xDoubleArray, 0, totalRange));
    DoubleValues yValues = new DoubleValues(Arrays.copyOfRange(yDoubleArray, 0, totalRange));
    DoubleSeries doubleSeries = new DoubleSeries(xValues, yValues);

    binding.sciChart.getRenderableSeries().add(lineSeries);
    binding.sciChart.getRenderableSeries().add(staticLineSeries);

    binding.sciChart.setRenderSurface(new RenderSurface(getContext()));

    Collections.addAll(binding.sciChart.getYAxes(), yAxis);
    Collections.addAll(binding.sciChart.getXAxes(), xAxis);
    Collections.addAll(binding.sciChart.getChartModifiers(), chartModifiers);
    Collections.addAll(binding.sciChart.getAnnotations(), verticalLine);

    staticData.append(doubleSeries.getxValues(), doubleSeries.getyValues());
    lineData.setAcceptsUnsortedData(true);

    begin();
}
Version
3.0.0.4253
  • You must to post comments
0
0

Hi there,

The only thing which I see that can be improved – creation of double arrays which are GC after using in run(). This can cause signifant degradation of performance if size of array is large or/and it’s recreated many times.

I would suggest to cache DoubleValues outside run() call and reuse them.

private Runnable mRunnable = new Runnable() {
private final DoubleValues xValues = new DoubleValues();
private final DoubleValues yValues = new DoubleValues();
@Override
public void run() {
    forceRunInPauseMode = false;

    getActivity().runOnUiThread(() -> {
        currentTime = (int) exoPlayer.getCurrentPosition();
        binding.tvCurrentDuration.setText(MiliToTimeConverter.milliToTime(currentTime));
    });

    int currentRange = currentTime * 2;


    if (!isDraw) {
        xValues.setSize(xDoubleArray.length);
        yValues.setSize(yDoubleArray.length);

        System.arraycopy(xDoubleArray, 0, xValues.getItemsArray(), 0, xDoubleArray.length);
        System.arraycopy(yDoubleArray, 0, yValues.getItemsArray(), 0, yDoubleArray.length);

        lineData.append(xValues, yValues);
        isDraw = true;
    }
    xVisibleRange.setMinMax(currentRange - visibleInterval / 2, currentRange + visibleInterval / 2);
}};

Best regards,
Yura

  • Yura Khariton
    Without profiling the application it’s hard to tell why application lags. I couldn’t compile your code into project because of missing code pieces and this is the only thing which I noticed which could significantly harm performance. So there is nothing I can do in this case, unless you provide provide results of profiling or full project ( so I can run and profile on my computer )
  • abolfazl ghanbari
    My chart is very similar to the chart at the top of example https://www.scichart.com/example/android-audio-analyzer-chart-example/ . But my problem is that both in the example and in my chart, the chart is associated with vibration. Can this minor vibration be eliminated?
  • Yura Khariton
    It’s hard to understand what do you mean by ‘minor vibration’. Do you have some example, video or screenshot which demonstrates desired output vs current output?
  • abolfazl ghanbari
    After further investigation, I came to the conclusion that adding the following line would solve the problem : binding.sciChart.setRenderSurface(new RenderSurface(getContext())); or binding.sciChart.setRenderSurface(new RenderSurfaceGL(getContext())); But we don’t know which code line is better for each device. Can you guide me?
  • Yura Khariton
    Please take a look on this article from documentation which explains difference between existing renderers – https://www.scichart.com/documentation/android/current/webframe.html#Renderer%20Plugins.html
Showing 1 result
Your Answer

Please first to submit.

Try SciChart Today

Start a trial and discover why we are the choice
of demanding developers worldwide

Start TrialCase Studies