实时图表在GraphView库Android

时间:2016-06-15 11:32:42

标签: android graph out-of-memory real-time android-graphview

我正在使用GraphView库。我正通过蓝牙通过一些第三方设备绘制实时图表。

每秒连续发送50个样本。 我需要不断绘制它。

但是我需要在屏幕上显示大约360个样本,无论屏幕尺寸如何。

我的代码如下:

    class MyHandler extends Handler {

          private final WeakReference<HomeScreenActivity> mActivity;

            private MyHandler(HomeScreenActivity activity) {
                mActivity = new WeakReference<HomeScreenActivity>(activity);
            }

            /**
             * Method handleMessage.
             *
             * @param msg android.os.Message
             */
            public void handleMessage(android.os.Message msg) {
                final HomeScreenActivity parent = mActivity.get();
                Logger.log(Level.DEBUG, "HomeScreenActivity", "msg.what=" + msg.what);



                if (msg.what == Constants.PLETHY_1000) {
                        String str = (String) msg.obj;

                    final String[] arr = str.replace("[", "").replace("]", "").split(",");

                    for (int i = 0; i < arr.length; i++) {
                        mSeries2.appendData(new DataPoint(graph2LastXValue, Double.parseDouble(arr[i])), true,360);// change 360 to 40 and works fine  
                     graph2LastXValue++;

                    }
}
}

它适用于某些Android设备 但我的应用程序在其他设备上运行2分钟或3分钟后崩溃。

我的logcat会收到错误:

06-13 10:30:42.012 31412-31452/bpl.com.bpl.com.bploximeterdemo W/Adreno-GSL: <sharedmem_gpumem_alloc_id:1554>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
06-13 10:30:42.012 31412-31452/bpl.com.bpl.com.bploximeterdemo E/Adreno-GSL: <gsl_memory_alloc_pure:1500>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo W/Adreno-GSL: <sharedmem_gpumem_alloc_id:1554>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo E/Adreno-GSL: <gsl_memory_alloc_pure:1500>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo W/Adreno-GSL: <sharedmem_gpumem_alloc_id:1554>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo E/Adreno-GSL: <gsl_memory_alloc_pure:1500>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo W/Adreno-GSL: <sharedmem_gpumem_alloc_id:1554>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
06-13 10:30:42.022 31412-31452/bpl.com.bpl.com.bploximeterdemo E/Adreno-GSL: <gsl_memory_alloc_pure:1500>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.

我开始意识到这是一个记忆错误。

注意:当我降低maxdata点的限制时,屏幕上显示的时间会更长。

例如。如果我将最大数据点更改为360 t0 40,则会运行更长时间,例如25分钟。

测试它的设备:

Motorola 3rd gen(2gb RAM,Marshmallow)- works like a charm
Mi4i -(2GB RAM,Lollipop)- crashes after some time , error shown as above
Karbonn Titanium(1 GB RAm,Lollipop)-crashes after few secs ,error shown as above 

我不知道为什么会发生这种情况。感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

没有足够的信息可以确定这一点。是否有可用的堆栈跟踪?您能否在收到大致相同数量的数据后判断是否发生了崩溃?测试是否是这种情况的最简单方法是减慢进入应用程序的数据速率或间歇性地中断数据传输。如果减慢/中断数据不会减少/消除崩溃,那可能是内存泄漏所以我建议尝试泄漏金丝雀(https://github.com/square/leakcanary)。

如果减慢/中断数据传输的速度确实消除(或大规模减少)崩溃,我猜测OutOfMemory是由您的数据添加速度快于垃圾收集可以释放未使用数据所使用的内存引起的。

GraphView库中的追加数据操作如下所示:

public void appendData(E dataPoint, boolean scrollToEnd, int maxDataPoints) {
    checkValueOrder(dataPoint);

    if (!mData.isEmpty() && dataPoint.getX() < mData.get(mData.size()-1).getX()) {
        throw new IllegalArgumentException("new x-value must be greater then the last value. x-values has to be ordered in ASC.");
    }
    synchronized (mData) {
        int curDataCount = mData.size();
        if (curDataCount < maxDataPoints) {
            // enough space
            mData.add(dataPoint);
        } else {
            // we have to trim one data
            mData.remove(0);
            mData.add(dataPoint);
        }
    }

    // recalc the labels when it was the first data
    boolean keepLabels = mData.size() != 1;

    // update linked graph views
    // update graphview
    for (GraphView gv : mGraphViews) {
        gv.onDataChanged(keepLabels, scrollToEnd);
        if (scrollToEnd) {
            gv.getViewport().scrollToEnd();
        }
    }
}

它在ArrayList上使用.remove(),这不是一个非常有效的操作。如果将库源代码导入Android Studio并将本地副本添加到项目中,则将ArrayList替换为LinkedList(或者可能是更合适的并发集合)可能会解决问题。

final private List<E> mData = new ArrayList<E>();

到:

final private List<E> mData = new LinkedList<E>();
https://github.com/jjoe64/GraphView/blob/master/src/main/java/com/jjoe64/graphview/series/BaseSeries.java

中的

如果这确实解决了,那么值得向图书馆的维护者报告。

另一种选择是限制数据传输速率。例如,使用RxJava:https://github.com/ReactiveX/RxJava/wiki/Backpressure