Android内存之间的活动泄漏

时间:2013-01-31 07:28:30

标签: android memory-leaks

我正试图找出这个内存泄漏。

我有两个SurfaceViewsAB。我开始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);
    }
}

假设每次视图丢失或获得焦点时都会调用这些方法,这显然是错误的。我怎样才能重新组织这个呢?

5 个答案:

答案 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)

一些提示:

  • 完成活动后回收位图(例如onDestroy)
  • 尽可能使用应用程序上下文而不是活动本身作为上下文

答案 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();