最近在检查回顾代码时,发现了一个可优化的地方,同时想到在平时的开发中很多细微处我们通过对源码的稍微修改是可以提升程序的运行速度和性能的。话不多说,看代码。
private class ReadThread extends Thread {
private boolean isRun; //是否一直循环
@Override
public synchronized void start() {
isRun = true;
super.start();
}
private void stopRun() {
isRun = false;
interrupt();
}
@Override
public void run() {
super.run();
//判断进程是否在运行,更安全的结束进程
try {
while (isRun) {
byte[] buffer = new byte[100];
int size; //读取数据的大小
size = getSerialPort().getInputStream().read(buffer);
if (size > 32) {
String str = new String(buffer, 0, size).trim();
//传输的数据是数据加 空数据间隔 传送
if (!TextUtils.isEmpty(str)) {
// MyLog.myInfo("收到的数据" + str);
if (handler != null) {
Message msg = handler.obtainMessage(WEIGHT_NOTIFY_XS15, str);
handler.sendMessage(msg);
}
}
}
Thread.sleep(150);
}
} catch (IOException e) {
Log.e(TAG, "run: 数据读取异常:" + e.toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面的代码是我的原始代码,这是一个硬件的数据读取,需要循环读取串口数据,这时我发现代码有个地方是不合理的
while (isRun) {
byte[] buffer = new byte[100];
int size; //读取数据的大小
size = getSerialPort().getInputStream().read(buffer);
这个地方是不合理的,我觉得在while循环中不断的创建byte[],然后将串口中读取到的数据赋值其中。于是翻开 InputStream.read(byte b[]):
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
很明显 read(byte b[], int off, int len) 就是将你不断new byte[]的数组赋值,当无数据了后面默认补充为0。现在我知道我每次循环读的数据最长byte[]长度是60,然后有多种类型的数据,byte[]长度为 7 ,24, 32,53是代表不通含义的数据。我想用一个byte[]创建一次接收数据,不用循环new byte[]。那么用源码,你会发现如果第一次接收53长度的数据后,再接收byte[]长度7的数据,这是索引Index以后的数据不再是0而是53长度时的数据,这样和原本数据肯定不一样,不符合要求。所以对源码进行修改。
/*** * 称重的有效数据 一般是 57位 * * @param b 源数组 * @param off 起始位置 * @param len 数组 b 的数据长度length * @return 返回InputStream 中的byte 数据长度 * @throws IOException 抛出的异常 */ //TODO 待 移动到base类中 public synchronized int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = getSerialPortPrinter().getInputStream().read(); if (c == -1) { return -1; } b[off] = (byte) c; int i = 1; int size=1; //数据是否完了 boolean isOver = false; try { for (; i < len; i++) { c = getSerialPortPrinter().getInputStream().read(); if (c == -1) { isOver=true; } if(isOver){ b[off + i] = 0; }else { b[off + i] = (byte) c; if(c!=0){ size++; } } } } catch (IOException e) { e.printStackTrace(); } return size; }
通过上面的代码修改,这样每次用同一个byte[]就能接收原滋原味的数据,不用反复new byte[]。我想这对于while循环优化了不少吧。
private class ReadThread extends Thread {
private boolean isRun; //是否一直循环
@Override
public synchronized void start() {
isRun = true;
super.start();
}
private void stopRun() {
isRun = false;
interrupt();
}
@Override
public void run() {
byte[] buffer = new byte[60];
super.run();
//判断进程是否在运行,更安全的结束进程
try {
while (isRun) {
int size; //读取数据的大小
size = read(buffer,0,buffer.length);
String str = new String(buffer, 0, size).trim();
Thread.sleep(120);
}
} catch (IOException e) {
Log.e(TAG, "run: 数据读取异常:" + e.toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
好了上面就是对代码的一个小优化。在编码的过程中,我们是可以尝试对源码进行修改以符合自己的需要的,这样以少积多,就能对代码及系统有个巨大的提升。
这类优化可以在串口接收数据方面应用,很多需要从串口不断接收数据的程序都有一个while 循环不断new byte[]接收,很费资源。
上面是个人的体会积累,如有缺陷,请多指教。