数据在特定线程上正确收集,并在Bundle中100ms发送到我的主要活动.
主要活动包含来自achartengine库(lineChart类)的4个图表,使用GraphicalVIEw添加到其视图中
总而言之,每100毫秒,我的主要活动收到一个回调和
>复制捆绑包中的数据
>将其添加到4个不同的数据集中(XYMultipleSerIEsDataset)
>在包含数据集的4个图表上调用repaint()
调用重绘时,数据集将不会更新,直到下一个包从另一个线程到达,100毫秒后.我假设100毫秒应该足以重绘视图.
我在这里发布了一个包含数据集和视图的小版本,
以及实施和使用的主要活动的一部分
/** This class contains the data and renderer used to draw a chart */public class lineChartData {public static enum SerIEs {X,Y,Z};public static final int MAX_NB_VALUES_PER_SERIE = 1000;private XYMultipleSerIEsDataset mDataset = new XYMultipleSerIEsDataset();private XYMultipleSerIEsRenderer mRenderer = new XYMultipleSerIEsRenderer();private int[] mcolors = new int[]{color.RED,color.GREEN,color.BLUE};private GraphicalVIEw mChartVIEw;private boolean mFollow = true;private boolean mtouchedDown = false;public lineChartData(Context context,String Title,String[] serIEsnames){ // Since we save only 3 colors,the programm will not support more than 3 serIEs per chart for(int i = 0; i < serIEsnames.length; ++i) { XYSerIEs serIE = new XYSerIEs(serIEsnames[i].toString()); mDataset.addSerIEs(serIE); XYSerIEsRenderer serIERenderer = new XYSerIEsRenderer(); serIERenderer.setcolor(mcolors[i]); mRenderer.addSerIEsRenderer(serIERenderer); } mRenderer.setmargins(new int[] { 20,30,0 }); mRenderer.setLegendHeight(50); //mRenderer.setShowLegend(true); mRenderer.setChartTitle(Title); mRenderer.setmarginscolor(color.WHITE); mRenderer.setXAxisMax(SettingsActivity.DEFAulT_disPLAY_RANGE); mRenderer.setXAxisMin(0); mChartVIEw = ChartFactory.getlineChartVIEw(context,mDataset,mRenderer); mChartVIEw.repaint();}public voID addData(int serIEID,double x,double y){ mDataset.getSerIEsAt(serIEID).add(x,y);}public voID repaint(){ mChartVIEw.invalIDate();}public voID updatedisplayWindow(int displayRange){ if(!mFollow) { return; } double maxX = mDataset.getSerIEs()[0].getMaxX(); if(maxX > displayRange) { mRenderer.setXAxisMax(maxX); mRenderer.setXAxisMin(maxX-displayRange); } else { mRenderer.setXAxisMax(displayRange); mRenderer.setXAxisMin(0); }}public voID deleteoldestValues(){ XYSerIEs[] serIEs = mDataset.getSerIEs(); for(XYSerIEs serIE : serIEs) { while(serIE.getItemCount() > MAX_NB_VALUES_PER_SERIE) { serIE.remove(0); } }}}
创建4个图表:
protected voID onCreate(Bundle b){ mAccelChartVIEw = new lineChartData(this,getString(R.string.Accel),new String[] {getString(R.string.xAxis),getString(R.string.zAxis),getString(R.string.zAxis)}); mGyroChartVIEw = new lineChartData(this,getString(R.string.Gyro),getString(R.string.zAxis)}); mPressureChartVIEw = new lineChartData(this,getString(R.string.Pressure),new String[] {getString(R.string.pressureAxis)}); mEcgChartVIEw = new lineChartData(this,getString(R.string.ECG),new String[] {getString(R.string.ecgAxis)}); linearLayout layoutAccel = (linearLayout) findVIEwByID(R.ID.accelChart); linearLayout layoutGyro = (linearLayout) findVIEwByID(R.ID.gyroChart); linearLayout layoutPressure = (linearLayout) findVIEwByID(R.ID.pressureChart); linearLayout layoutEcg = (linearLayout) findVIEwByID(R.ID.ecgChart); layoutAccel.addVIEw(mAccelChartVIEw.getVIEw(),0); layoutGyro.addVIEw(mGyroChartVIEw.getVIEw(),0); layoutPressure.addVIEw(mPressureChartVIEw.getVIEw(),0); layoutEcg.addVIEw(mEcgChartVIEw.getVIEw(),0);}
更新图表
private voID updateVIEwUsingMessage(String action,Bundle newData) { if(action.equals(BluetoothCollecterThread.MSG_UPDATE_CHART)) { addFromBundle(newData,mLogger.isLogging()); mAccelChartVIEw.updatedisplayWindow(mdisplayRange); mAccelChartVIEw.deleteoldestValues(); mGyroChartVIEw.updatedisplayWindow(mdisplayRange); mGyroChartVIEw.deleteoldestValues(); mPressureChartVIEw.updatedisplayWindow(mdisplayRange); mPressureChartVIEw.deleteoldestValues(); mEcgChartVIEw.updatedisplayWindow(mdisplayRange); mEcgChartVIEw.deleteoldestValues(); mAccelChartVIEw.repaint(); mGyroChartVIEw.repaint(); mPressureChartVIEw.repaint(); mEcgChartVIEw.repaint(); }}
它可能看起来很大但实际上很容易.我有两个问题,我不知道是否有联系:
首先,每秒几次,一张图表中的第一个系列在另一张图表上绘制(见下图).我检查了我的代码,找不到任何解决方案.而且,它似乎真的是随机发生的,因此它看起来更像是来自achartengine库的并发问题.
这带来了我的第二个问题.日志显示来自垃圾收集器的消息过多,特别是WAIT_FOR_CONCURRENT_GC类型的消息被阻止,这显然是不好的.
我发现这个链接:http://www.voidcn.com/article/p-rembizwq-btn.html表明内存分配问题仍然存在于achartengine中,但最后一个版本应足以显示几个实时1000点的图形.即使我将数据更新设置为1秒而不是100毫秒,我仍然会遇到视觉故障
正确的行为:4个图表实时更新(两个第一个有3个系列,两个最后有1个系列)
http://s903.photobucket.com/user/bperreno/media/correct_zpsebd731f6.png.html?sort=3&o=1
错误:图表2中的红色系列显示在其他图表上
http://s903.photobucket.com/user/bperreno/media/wrong1_zpsd33eec83.png.html?sort=3&o=0
数据正在实时移动,但有时,第二张图片中显示的故障发生,一两帧,然后消失.
有没有人知道如何,至少,修复显示问题?也许希望告诉我如何解决achartengine垃圾收集的过度使用问题
非常感谢!
编辑04.12.2013
我现在使用achartengine源而不是.jar,所以我可以查看值.看到“setInScroll”不起作用后,我看了一下代码.在GraphicalVIEw.onDraw方法中,我比较了setInScroll为true或false时使用的值.
int top = mRect.top;int left = mRect.left;int wIDth = mRect.wIDth();int height = mRect.getheight();if(mRenderer.isInScroll()){ top = 0; left = 0; wIDth = getMeasureDWIDth(); height = getMeasuredHeight();}
从mRect或getMeasuredXXX()传来的值始终相同.在这两种情况下,顶部和左侧都是零.所以(至少在这种情况下),inScroll = true无效
解决方法 好的,我正在回答我的问题:经过几次测试后,我发现当在achartengine lib上执行太多 *** 作时,这是一个很容易出现的问题.
繁重的行动似乎包括在内
>删除一个点
>设置X最大显示值
>清爽
所以我能做的最好的办法就是将X max位置设置得更远,所以我只需要偶尔更新一次(例如每秒一次)
向库中添加允许一次删除多个点的方法也很有用.删除当前是O(n)并且一个接一个地删除m个点因此是O(nm).
请注意,比我的galaxy S2更强大的设备(如S4mini)处理显示器没有毛刺.但效率仍然是更多图表和更高频率的问题.
4个图表达到10 FPS并不是我真正称之为实时的
总结以上是内存溢出为你收集整理的android – aChartEngine:如何显示实时更新全部内容,希望文章能够帮你解决android – aChartEngine:如何显示实时更新所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)