本文是参考网络上的资源,再结合自己的小学生逻辑,写的一个动态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]));
}
}
}
到此就结束了,有什么好的方法不用每次都重新绘图来提升性能,求告知。
附上从网上找的获取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;
}