Android开发中的hellocharts绘制动态折线图初试

本文是参考网络上的资源,再结合自己的小学生逻辑,写的一个动态hellocharts折线图的简单例子,以后自己要用的时候再来看看。

我用的是hellocharts-library-1.5.8.jar。

小学生思路:

1、准备一组横、纵坐标,先能绘制一个静态的折线图,给自己点信心。

2、根据某种原则,生成一组新的横、纵坐标。清空原来的图像,再把这两组新坐标对应的折线图绘制出来。

3、弄一个定时器或者其他的方式,每隔一段时间重复第二步,那么折线图不就动起来了吗,美滋滋。

这里需要注意几点,写代码之前,我忍不住说出来:

  • 本文先只管实现,没研究源码,作者水平还不够。。。后面再提高吧
  • 问题之一:由于demo的横坐标是时间,希望是每1秒才更新1次,所以注意可能出现的某相邻两个横坐标的时间是一样的(更新过快)。
  • 问题之二:注意横、纵坐标的一一绑定关系。不要开始横坐标13:00点对应数字45,等一会13:00点又对应数字11了。
  • 问题之三:我在了解了hellocharts皮毛之后,膨胀了,想用折线图实现监测设备cpu使用率。后来发现,我做不到每一秒刷新一次图表,因为那台机器大概要4秒才能获得一次cpu的使用率信息。但是换了一台机器又可以每秒刷新。所以可能是设备的性能问题,也可能是我获取cpu使用率的位置不对。
  • 问题之四:每次开始运行,会有一点延时才能绘制出来,或者重新进入折线图所在activity的时候,绘制缓慢.,不能忍。
  • 问题之五:last but not least,要想实现连续的绘制,拿横坐标来说,假设某一时间为[4,5,6,7,8],那么下一刻我就想横坐标变成[5,6,7,8,9],把这组坐标绘制出来就行,这类似队列先进先出,可以写个简单的方法即可实现(我的小学生想法)。
  • 问题之六:例子是每次重新绘制整个折线图,我最开始想的应该可能先初始化一次折线图的一些设置,有些属性不需要重复设置吧。后面只需要传入横纵坐标就行了。但是。。。我没做出来,很多属性似乎都需要重新设置。 

上面就是这个逻辑上的部分可能问题。

代码及注释如下(应该是可以直接使用,前提是导入了hellocharts的jar):

例子是没有做折线图缩放的,可以设置这个属性。

public class MainActivity extends AppCompatActivity {

    private LineChartView lineChartView; //折线图view
    private List<PointValue> mAxisYValues = new ArrayList<>(); //LineChartView上的Y轴坐标
    private List<AxisValue> mAxisXValues = new ArrayList<>();  //LineChartView上的X轴坐标
    private SimpleDateFormat DATE_FORMAT_TIME = new SimpleDateFormat("HH:mm:ss");

    String axisX[] = {"0", "0", "0", "0", "0", "0"};  //初始状态横坐标
    int axisY[] = {0, 0, 0, 0, 0, 0};  //初始状态纵坐标


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lineChartView = findViewById(R.id.chart);

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                refreshAxis();              //更新mPointValues  mAxisXValues
                refreshLineChart(mAxisYValues, mAxisXValues, lineChartView);  //绘图
                SystemClock.sleep(50); //休眠一下再清除旧图
                mAxisXValues.clear();       //清除原有数据,不然会叠加绘制坐标点
                mAxisYValues.clear();
            }
        }, 500, 1000);
    }

    private void refreshLineChart(List<PointValue> mAxisYValues,
                                        List<AxisValue> mAxisXValues,
                                        LineChartView lineChart) {
        Line line = new Line(mAxisYValues).setColor(Color.parseColor("#E5C924"));  //折线的颜色
        List<Line> lines = new ArrayList<Line>();
        //常见的折线图设置
        line.setShape(ValueShape.CIRCLE);   //折线图上每个数据点的形状  这里是圆形 (有三种 :ValueShape.SQUARE  ValueShape.CIRCLE  ValueShape.SQUARE)
        line.setCubic(false);               //曲线是否平滑
        line.setStrokeWidth(1);             //线条的粗细
        line.setFilled(true);               //是否用折线的颜色填充折线到X轴之间的区域
        line.setHasLabels(false);           //折线上是否加上具体的纵坐标值
        line.setHasLines(true);             //是否用直线显示,如果为false,折线上只有点没有线
        line.setHasPoints(true);            //是否显示圆点,如果为false,就不会在图上画一个较大的实心圆点
        lines.add(line);
        LineChartData data = new LineChartData();
        data.setLines(lines);

        //X轴的常见设置
        Axis axisX = new Axis();
        axisX.setHasTiltedLabels(false);  //X轴内容字体(如前面提到的时间)是斜的还是直的,true是倾斜的
        axisX.setTextColor(Color.WHITE);  //设置X轴内容颜色
        axisX.setName("时间(24小时制)");  //折线图的X轴名称,表示X轴是什么类型的信息
        axisX.setTextSize(10);            //设置字体大小
        axisX.setValues(mAxisXValues);    //填充X轴的坐标值
        data.setAxisXBottom(axisX);       //x轴在底部

        //Y轴的常见设置
        Axis axisY = new Axis();
        axisY.setHasLines(true);
        axisY.setName("cpu使用率(%)");    //代码里是随机数模拟cpu使用率
        axisY.setTextSize(10);            //设置字体大小
        axisY.setTextColor(Color.WHITE);  //设置字体颜色
        //纵轴显示几个刻度,这里假如是4个
        int dataY[] = {0, 25, 50, 75, 100};
        List<AxisValue> values = new ArrayList<>();
        for (int i : dataY) {
            AxisValue value = new AxisValue(i);
            values.add(value);
        }
        axisY.setValues(values);
        //Y轴设置在左边,推测setAxisYRight就是在折线图的右边
        data.setAxisYLeft(axisY);

        //其他的设置
        lineChart.setInteractive(false);          //设置不支持交互,交互是指你可以触摸图表,会给你相应的响应,比如缩放,向后平移
        lineChart.setLineChartData(data);
        lineChart.setVisibility(View.VISIBLE);
        lineChart.setEnabled(true);

        //我的理解是固定Y轴的范围,如果没有下面的内容,Y轴的范围会根据数据的最大值和最小值决定
        //导致纵轴刻度并不能一直保持{0, 25, 50, 75, 100}。而是随着具体的Y轴坐标变化
        Viewport v = new Viewport(lineChart.getMaximumViewport());
        v.bottom = 0f;
        v.top = 100f;
        //固定Y轴的范围,
        lineChart.setMaximumViewport(v);
        lineChart.setCurrentViewport(v);
    }
    /**
     * 先进先出,比如横坐标是  1 2 3 4 ,马上来了5,所以应该变成2 3 4 5
     *
     * @param axisX 当前横坐标数组
     * @param newX  下一个最新的横坐标值
     * @param axisY 当前纵坐标数组
     * @param newY  下一个最新的纵坐标值
     */
    private void refreshXY(String axisX[], String newX, int axisY[], int newY) {
        if (newX.equals(axisX[axisX.length - 1])) //避免连续两个X坐标一样(如果是其它类型的横坐标,可能允许是相同的)
            return;
        for (int i = 0; i < axisX.length - 1; i++) {
            axisX[i] = axisX[i + 1];
            axisY[i] = axisY[i + 1];
        }
        axisX[axisX.length - 1] = newX;
        axisY[axisY.length - 1] = newY;
    }

    /**
     * 填充新折线图的横纵坐标数据
     */
    private void refreshAxis() {
        Random rand = new Random(); //用随机数模拟纵坐标
        String date = DATE_FORMAT_TIME.format(new Date(System.currentTimeMillis())); //用时间充当横坐标

        refreshXY(axisX, date, axisY, rand.nextInt(90));

        for (int i = 0; i < axisX.length; i++) { //把普通横纵坐标填充为折线图的坐标格式
            mAxisXValues.add(new AxisValue(i).setLabel(axisX[i]));
            mAxisYValues.add(new PointValue(i, axisY[i]));
        }
    }
}

error

到此就结束了,有什么好的方法不用每次都重新绘图来提升性能,求告知。


附上从网上找的获取cpu占用率的方法:

    private int getCpuRate() {
        StringBuilder tv = new StringBuilder();
        int rate = 0;
        try {
            String Result;
            Process p;
            p = Runtime.getRuntime().exec("top -n 1");

            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((Result = br.readLine()) != null) {
                if (Result.trim().length() < 1) {
                    continue;
                } else {
                    String[] CPUusr = Result.split("%");
                    tv.append("USER:" + CPUusr[0] + "\n");
                    String[] CPUusage = CPUusr[0].split("User");
                    String[] SYSusage = CPUusr[1].split("System");
                    tv.append("CPU:" + CPUusage[1].trim() + " length:" + CPUusage[1].trim().length() + "\n");
                    tv.append("SYS:" + SYSusage[1].trim() + " length:" + SYSusage[1].trim().length() + "\n");

                    rate = Integer.parseInt(CPUusage[1].trim()) + Integer.parseInt(SYSusage[1].trim());
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return rate;
    }

猜你喜欢

转载自blog.csdn.net/qq_31371757/article/details/85339908