【问题标题】:Real Time Graph is inconsistent in GraphView Library AndroidGraphView Library Android中的实时图不一致
【发布时间】:2016-06-15 11:32:41
【问题描述】:

我正在使用 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++;

                    }
}
}

它适用于某些安卓设备 但我的应用程序在其他设备上运行 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.

我意识到这是一个内存错误。

注意:当我降低我的最大数据点的限制时,它会在屏幕上显示的时间更长。

例如。如果我将最大数据点更改为 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 

我不知道为什么会这样。感谢任何帮助。

【问题讨论】:

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


    【解决方案1】:

    没有足够的信息来确定这一点。是否有可用的堆栈跟踪?在收到大致相同数量的数据后,您能否判断崩溃是否发生?测试是否是这种情况的最简单方法是减慢进入应用程序的数据速率或间歇性中断数据传输。如果减慢/中断数据并不能减少/消除崩溃,则可能是内存泄漏,因此我建议尝试 Leak Canary (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

    【讨论】:

    • 它只在某些设备上崩溃,它会在 1 分钟后崩溃,即绘制 300 个样本。起初我以为是垃圾收集问题,但它并没有给我内存错误。它没有给我任何堆栈跟踪
    • Leak Canary 或 Facebook 的 Infer 旨在捕获内存泄漏。它们可能值得一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多