我正试图找出这个内存泄漏。
我有两个SurfaceViews
,A
和B
。我开始A
,然后导航到B
,然后按后退按钮返回A
,然后再次导航到B
。
每次执行此操作时,我都可以看到分配的内存会增加,最终会出现内存不足错误。
以下是我从与B
SurfaceView
内导航至A
的方法
Context context = this.getContext();
Intent i =new Intent(context, StartCareer.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
在两个视图中,我都有很多Bitmaps绘图。在B
中,我找不到对A
的任何引用,并且在我可以想到的上下文之外的唯一引用是对我所拥有的Global类的引用。我还在后台进行了一些分析工作。这可能是一百万种不同的东西,我想是
我在Eclipse上有DDMS视图,但我不确定我在看什么,或者如何找到不断重复的确切对象。
我接受DDMS分配跟踪器上的崩溃课程/教程,或者有人指出我做错了什么。
其他信息:
我在SurfaceView
上绘制了一些位图。来自B
的示例包括:
////At class level
Bitmap rightB,leftB;
////In the constructor
rightB = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.right), 100,75, true);
////In doDraw
canvas.drawBitmap(rightB, rbX, rbY, null);
我的onDestroys
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()){
mThread.setMenuRunning(false);
}
}
所以我运行MAT并发现一次泄漏,至少。我Thread
继续重新创建。
这是做什么的。
@Override
public void surfaceCreated(SurfaceHolder holder) {
loading=false;
if (!mThread.isAlive()){
mThread = new ViewThread(this);
mThread.setMenuRunning(true);
mThread.start();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()){
mThread.setMenuRunning(false);
}
}
假设每次视图丢失或获得焦点时都会调用这些方法,这显然是错误的。我怎样才能重新组织这个呢?
答案 0 :(得分:5)
在您应用的onDestroy()
和onstop()
中调用此方法。
private void unbindDrawables(View view) {
Log.d(TAG,"in unbindDrawables");
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
view.setBackgroundResource(0);
Log.d(TAG,"removed views");
//finish();
}
}
答案 1 :(得分:3)
使用DDMS创建堆转储(* .hprof文件),“堆启用”附近的按钮。
然后使用标准sdk工具“*.hprof
”将此文件转换为另一个hprof-conv.exe
然后下载eclipse内存分析器工具(http://www.eclipse.org/mat/)(我已将其作为独立工具下载),并打开新的*.hprof file
,
它有“memory leak analyzer
”,可以告诉你哪里可能有错误(它说bufferObjectManager太大了,占用了整个内存的50%)。
当我清理它时(BufferObjectManager.getActiveInstance().unloadBufferObject(((RectangularShape) obj).getVertexBuffer());)
它有点帮助,但仍有问题。
如果你完全清除这个缓冲区,你将失去纹理等。如果问题只是在关闭应用程序时内存泄漏,那么避免这个问题的方法是明确的(onDestroy();
)这个缓冲区。
答案 2 :(得分:3)
一些提示:
答案 3 :(得分:1)
尝试在活动的onDestroy()中回收()您的位图。
答案 4 :(得分:0)
您需要做的是explained in detail here。对于您的具体问题,您需要这样做
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
(int) y, true);
b.recycle();