我编写了一个程序,它以字节 [] 的形式从套接字读取图像,然后尝试在屏幕上显示它们。我关注了一些我发现的链接,说最好的方法是使用 SurfaceView。我正在尝试分配一个字节数组,该数组将占我需要的最大图像,然后不断为我收到的新图像使用相同的内存空间。这样内存就没有机会收集垃圾了。
我想我已经将问题缩小到“BitmapFactory.decodeByteArray(f, 0, fileSize);”的函数调用。我认为这个调用每次都会创建一个新的位图,一旦方法返回,它就会被 GC 处理。我尝试使用 inMutable 和 inBitmap 字段,但没有运气,因为图像的大小每次都在变化。不过,我可能做错了什么。如果有人有任何使用它的经验并且对他们有用,请告诉我。每次 byte[] 大小甚至仅更改 10 个元素。
我正在尝试尽可能快地显示我正在阅读的图像,并希望重用相同的内存空间/位图,这样我就不必继续承担 30 毫秒的垃圾收集成本。有谁知道我如何避免垃圾收集,或者至少将其最小化?图像为 640x480 和 1280x720。下面是读取图像并将其与 LogCat 输出一起显示的代码片段。任何帮助,将不胜感激。谢谢。
static byte[] f = new byte[250000]; // allocate enough memory space for biggest image
private TutorialThread _thread;
class Panel extends SurfaceView implements SurfaceHolder.Callback {
/* On start up connect socket */
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
if (connectSockets) {
s2 = connect(ip, s2, port);
}
}
/*
* OnDraw - Take the byte[] and use Bitmap.decodeByteArray to decode
* Image and then draw it on canvas
*
* (Slow, Causing 30ms delay due to Garbage Collection)
*/
@Override
public void onDraw(Canvas canvas) {
Bitmap i = BitmapFactory.decodeByteArray(f, 0, fileSize);
canvas.drawBitmap(i, 10, 10, null);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or
// else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
@Override
public void run() {
Canvas c = null;
byte[] header = new byte[16];
while (_run) {
Log.d("Brian", "Running");
if (s2 != null) { // if socket isCreated
int bytesRead = 0;
int totalBytesRead = 0;
fileSize = 0;
/*
* read the header that contains the filesize, height, and
* width
*
* don't break until we read all header values
*/
while (totalBytesRead != (header.length)) {
try {
bytesRead = s2.getInputStream().read(header,
totalBytesRead,
(header.length - totalBytesRead));
} catch (IOException ex) {
}
if (bytesRead == -1) {
} else {
totalBytesRead += bytesRead;
}
}
// convert the filesize from bytes to int
fileSize = (fileSize << 8) + (header[0] & 0xff);
fileSize = (fileSize << 8) + (header[1] & 0xff);
fileSize = (fileSize << 8) + (header[2] & 0xff);
fileSize = (fileSize << 8) + (header[3] & 0xff);
bytesRead = 0;
// read the entire file. don't break until we read
// everything
do {
bytesRead = readChunk(s2, bytesRead, fileSize, f);
} while (bytesRead != fileSize);
} else {
Log.d("Brian", "Socket Null");
}
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
07-05 09:13:21.980: D/dalvikvm(25075): GC_FOR_ALLOC freed 0K, 6% free 7040K/7431K, paused 18ms
07-05 09:13:22.010: D/dalvikvm(25075): GC_CONCURRENT freed <1K, 6% free 7040K/7431K, paused 4ms+2ms
07-05 09:13:22.040: D/dalvikvm(25075): GC_EXPLICIT freed 600K, 14% free 6440K/7431K, paused 1ms+2ms
07-05 09:13:22.060: D/dalvikvm(25075): GC_FOR_ALLOC freed <1K, 14% free 6440K/7431K, paused 19ms
07-05 09:13:22.060: I/dalvikvm-heap(25075): Grow heap (frag case) to 6.994MB for 614416-byte allocation
07-05 09:13:22.080: D/dalvikvm(25075): GC_FOR_ALLOC freed 0K, 6% free 7040K/7431K, paused 21ms
07-05 09:13:22.120: D/dalvikvm(25075): GC_CONCURRENT freed <1K, 6% free 7040K/7431K, paused 3ms+2ms
07-05 09:13:22.150: D/dalvikvm(25075): GC_EXPLICIT freed 600K, 14% free 6440K/7431K, paused 2ms+2ms
07-05 09:13:22.170: D/dalvikvm(25075): GC_FOR_ALLOC freed <1K, 14% free 6440K/7431K, paused 19ms
07-05 09:13:22.170: I/dalvikvm-heap(25075): Grow heap (frag case) to 6.994MB for 614416-byte allocation
07-05 09:13:22.190: D/dalvikvm(25075): GC_FOR_ALLOC freed 0K, 6% free 7040K/7431K, paused 19ms
07-05 09:13:22.220: D/dalvikvm(25075): GC_CONCURRENT freed <1K, 6% free 7040K/7431K, paused 2ms+2ms
07-05 09:13:22.250: D/dalvikvm(25075): GC_EXPLICIT freed 600K, 14% free 6440K/7431K, paused 2ms+1ms
07-05 09:13:22.270: D/dalvikvm(25075): GC_FOR_ALLOC freed <1K, 14% free 6440K/7431K, paused 18ms
07-05 09:13:22.270: I/dalvikvm-heap(25075): Grow heap (frag case) to 6.994MB for 614416-byte allocation