我正在开发一个使用MjpegView(流媒体视频的自定义视图)的Android应用程序。当用户第一次进入应用流媒体时 效果很好,但是当用户开始转到其他屏幕,然后返回到流媒体屏幕时,应用程序变得比平常慢。
在阅读了几篇关于内存泄漏的文章后发现他们扔掉了eclipse,我试着查看我的应用程序并注意到每次当用户转到其他屏幕(流媒体屏幕除外)时,流媒体的线程仍然存在,是吗正常?
public class MjpegView extends SurfaceView implements SurfaceHolder.Callback
{
public final static int POSITION_UPPER_LEFT = 9;
public final static int POSITION_UPPER_RIGHT = 3;
public final static int POSITION_LOWER_LEFT = 12;
public final static int POSITION_LOWER_RIGHT = 6;
public final static int SIZE_STANDARD = 1;
public final static int SIZE_BEST_FIT = 4;
public final static int SIZE_FULLSCREEN = 8;
private MjpegViewThread thread;
private MjpegInputStream mIn = null;
private boolean showFps = true;
private volatile boolean mRun = false; //volatile for fixing JIT unchanied all for thread => accures when opening and then closing drawer
private boolean surfaceDone = false;
private Paint overlayPaint;
private int overlayTextColor;
private int overlayBackgroundColor;
private int ovlPos;
private int dispWidth;
private int dispHeight;
private int displayMode;
private boolean resume = false;
private Context context;
private int streamWidth;
private int streamHeight;
public class MjpegViewThread extends Thread
{
private SurfaceHolder mSurfaceHolder;
private int frameCounter = 0;
private long start;
private Bitmap ovl;
public MjpegViewThread(SurfaceHolder surfaceHolder, Context context)
{
mSurfaceHolder = surfaceHolder;
}
private Rect destRect(int bmw, int bmh)
{
int tempx;
int tempy;
if (displayMode == MjpegView.SIZE_STANDARD)
{
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_BEST_FIT)
{
float bmasp = (float) bmw / (float) bmh;
bmw = dispWidth;
bmh = (int) (dispWidth / bmasp);
if (bmh > dispHeight)
{
bmh = dispHeight;
bmw = (int) (dispHeight * bmasp);
}
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
return null;
}
public void setSurfaceSize(int width, int height)
{
synchronized (mSurfaceHolder)
{
dispWidth = width;
dispHeight = height;
}
}
private Bitmap makeFpsOverlay(Paint p, String text)
{
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
int bwidth = b.width() + 2;
int bheight = b.height() + 2;
Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
p.setColor(overlayBackgroundColor);
c.drawRect(0, 0, bwidth, bheight, p);
p.setColor(overlayTextColor);
c.drawText(text, -b.left + 1, (bheight / 2) - ((p.ascent() + p.descent()) / 2) + 1, p);
return bm;
}
public void run()
{
start = System.currentTimeMillis();
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
int width;
int height;
Rect destRect;
Canvas c = null;
Paint p = new Paint();
String fps = "";
try
{
if (mIn != null && mRun)
{
//clear the buffer when the user in other place except measurement screen
int availableBytes = mIn.available();
mIn.skipBytes(availableBytes);
}
}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (mRun)
{
if (surfaceDone)
{
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
try
{
if (mIn != null && c != null)
{
Bitmap bm = mIn.readMjpegFrame();
destRect = destRect(bm.getWidth(), bm.getHeight());
if (streamHeight == -1 && streamWidth == -1)
{
streamWidth = bm.getWidth();
streamHeight = bm.getHeight();
}
c.drawColor(Color.BLACK);
c.drawBitmap(bm, null, destRect, p);
if (showFps)
{
p.setXfermode(mode);
if (ovl != null)
{
height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom - ovl.getHeight();
width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right - ovl.getWidth();
c.drawBitmap(ovl, width, height, null);
}
p.setXfermode(null);
frameCounter++;
if ((System.currentTimeMillis() - start) >= 1000)
{
fps = String.valueOf(frameCounter) + "fps";
frameCounter = 0;
start = System.currentTimeMillis();
ovl = makeFpsOverlay(overlayPaint, fps);
}
}
}
}
catch (IOException e)
{
}
catch (IllegalArgumentException e1)
{
Log.d("anton", "IllegalArgumentException");
}
}
}
finally
{
if (c != null) mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
public int getStreamWidth()
{
return streamWidth;
}
public int getStreamHeight()
{
return streamHeight;
}
private void init(Context context)
{
this.context = context;
streamHeight = -1;
streamWidth = -1;
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new MjpegViewThread(holder, context);
setFocusable(true);
if (!resume)
{
resume = true;
overlayPaint = new Paint();
overlayPaint.setTextAlign(Paint.Align.LEFT);
overlayPaint.setTextSize(12);
overlayPaint.setTypeface(Typeface.DEFAULT);
overlayTextColor = Color.WHITE;
overlayBackgroundColor = Color.BLACK;
ovlPos = MjpegView.POSITION_LOWER_RIGHT;
displayMode = MjpegView.SIZE_STANDARD;
dispWidth = getWidth();
dispHeight = getHeight();
Log.i("AppLog", "init");
}
}
public void startPlayback()
{
if (mIn != null)
{
mRun = true;
if (thread.getState() != Thread.State.TERMINATED)
{
thread.start();
}
else
{
resumePlayback();
}
}
}
public MjpegInputStream getStream()
{
return mIn;
}
public boolean isStreamingRunning()
{
return mRun;
}
public void resumePlayback()
{
mRun = true;
init(context);
Log.i("AppLog", "resume");
thread.start();
}
public void stopPlayback()
{
streamHeight = -1;
streamWidth = -1;
mRun = false;
boolean retry = true;
while (retry)
{
try
{
thread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
public MjpegView(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
public void surfaceChanged(SurfaceHolder holder, int f, int w, int h)
{
thread.setSurfaceSize(w, h);
}
public void surfaceDestroyed(SurfaceHolder holder)
{
surfaceDone = false;
stopPlayback();
}
public MjpegView(Context context)
{
super(context);
init(context);
}
public void surfaceCreated(SurfaceHolder holder)
{
surfaceDone = true;
}
public void showFps(boolean b)
{
showFps = b;
}
public void setSource(MjpegInputStream source)
{
mIn = source;
startPlayback();
}
//for swapping streams small/big mjpeg surfaces
public void setStreamSource(MjpegInputStream source)
{
mIn = source;
}
public void setOverlayPaint(Paint p)
{
overlayPaint = p;
}
public void setOverlayTextColor(int c)
{
overlayTextColor = c;
}
public void setOverlayBackgroundColor(int c)
{
overlayBackgroundColor = c;
}
public void setOverlayPosition(int p)
{
ovlPos = p;
}
public void setDisplayMode(int s)
{
displayMode = s;
}
@Override
public boolean performClick()
{
// TODO Auto-generated method stub
return super.performClick();
}
}
答案 0 :(得分:0)
您必须记住活动/片段的stopPlayback()
或freeCameraMemory()
方法中的onPause()
和onStop()