我寫了一個程序,它以字節[]的形式從套接字中讀取圖像,然後嘗試在屏幕上顯示它們。我跟着我發現的一些鏈接,說最好的方法是使用SurfaceView。我試圖分配一個字節數組,它將佔用我需要的最大圖像,然後不斷使用相同的內存空間來存儲我接收到的新圖像。這樣記憶就沒有機會收集垃圾了。提高圖像/位圖顯示速度Android
我想我已經將問題縮小到了「BitmapFactory.decodeByteArray(f,0,fileSize);」的函數調用。我認爲這個調用每次都會創建一個新的位圖,只要方法返回,它就會被GC化。我試圖使用inMutable和inBitmap字段,但沒有運氣,因爲圖像的大小每次都會改變。雖然我可能做了錯誤的事情。如果任何人有使用它的經驗,並且爲他們工作,請讓我知道。每次byte []大小隻有10個元素髮生變化。
我試圖顯示我正在閱讀的圖像儘可能快,並且希望重複使用相同的內存空間/位圖,這樣我就不必保持浪費30ms的垃圾回收成本。有誰知道我可以如何避免垃圾收集,或者至少將其最小化?圖像是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
感謝您的快速響應。我已經將decodeByteArray移出了onDraw函數,但仍然存在相同的問題。基本上這就是我正在做的。我正在等待從套接字讀取整個緩衝區,然後我會調用正在進行解碼和繪製的onDraw函數。我將解碼移到了TutorialThread內部類上方,正好位於測試的上方,同樣運氣。我認爲問題出在我稱之爲decodeByteArray函數的地方,它總是會導致垃圾收集。有關如何解決該函數調用的任何想法?謝謝。 – blouro 2012-07-05 13:41:30
如果您在創建新位圖時必須創建一個新位圖,則不需要。你幾乎必須使用BitmapFactory來解碼位數組。垃圾收集發生在舊位圖被丟棄時(並且可能會在函數本身中發生一些清理)。 您可以通過將舊位圖放入軟參考中來減輕影響。它會緩存它,直到內存需要,然後將被扔掉。 – DeeV 2012-07-05 14:05:25