我的Android应用程序中不断运行以下CountDownTimer
。
CountDownTimer timer_status;
timer_status = new CountDownTimer(1000,1000) {
List<Integer> lst = new ArrayList<Integer>();
int k=0;
@Override
public void onTick(long millisUntilFinished) {
String S = "";
k=0;
byte[] writeBuffer = new byte[8];
for (int value : lst) {
if(k==8) {
k=0;
S="";
}
S = S + String.format("%02x ", value).toUpperCase();
writeBuffer[k] = (byte) value;
k++;
}
editSent.setText(S);
}
每个循环,应用程序从byte[]
整数创建一个新的List
缓冲区。
它工作正常,但在LogCat中生成GC_FOR_ALLOC
。
03-05 11:12:41.330: D/dalvikvm(21178): GC_FOR_ALLOC freed 511K, 19% free 4662K/5720K, paused 14ms, total 14ms
03-05 11:12:42.250: D/dalvikvm(21178): GC_FOR_ALLOC freed 511K, 19% free 4662K/5720K, paused 15ms, total 15ms
GC_FOR_ALLOC被触发,因为堆上没有足够的内存来执行分配。在创建新对象时可能会触发。
如何改进此foreach
循环,在堆上留下足够的内存?
答案 0 :(得分:1)
StringBuilder sb = new StringBuilder();
k=0;
byte[] writeBuffer = new byte[8];
for (int value : lst) {
if(k==8) { k=0; sb.setLength(0);
}
sb.append(String.format("%02x ", value));
writeBuffer[k] = (byte) value; k++;
}
editSent.setText(sb.toString().toUpperCase());
除StringBuilder
之外,我想指出,正常for
的效果优于Android中的foreach
,因为foreach
循环会创建一个隐藏的Iterator
对象。因此,请避免在Android中使用性能关键代码中的for-each。
另外,如果可能的话,使用普通Array
作为原始类型而不是ArrayList
,因为在每个循环中都会发生自动装箱/拆箱,这会影响您的性能。
答案 1 :(得分:-1)
使用StringBuilder是一回事(见注释)。
您还可以避免局部变量S
和writeBuffer
,而是使用类变量,这有效地重复使用每个调用,而不是将它们传递给垃圾回收。