5

我试图查明这个内存泄漏。

我有两个SurfaceViews和。我开始,然后导航到,然后按返回按钮返回到,然后我再次导航到。ABABAB

每次执行此操作时,我都可以看到分配的内存增加,最终会出现内存不足错误。

这是我从连接到B内部导航到的方式SurfaceViewA

        Context context =  this.getContext();
        Intent i =new Intent(context, StartCareer.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(i);

在这两种视图中,我都有很多位图绘图。在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,至少发现了一个漏洞。我的ThreadKeeps 正在重新创建。这是在做什么。

@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);
    }
}

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

4

5 回答 5

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();
        }
 }
于 2013-01-31T07:45:39.747 回答
3

使用 DDMS 创建堆转储(*.hprof 文件),“堆启用”附近的按钮。

*.hprof然后使用标准 sdk 工具“ hprof-conv.exe”将此文件转换为另一个文件

然后下载eclipse内存分析工具(http://www.eclipse.org/mat/)(我已经下载它作为独立工具),打开你的新的*.hprof file,它有“ memory leak analyzer”,可以告诉你哪里可能有错误(它说 bufferObjectManager 太大,占用了总内存的 50% 以上)。

当我清理它时(BufferObjectManager.getActiveInstance().unloadBufferObject(((RectangularShape) obj).getVertexBuffer());)它有一点帮助,但仍然有问题。

如果您完全清除此缓冲区,您将失去纹理等。如果问题仅在于关闭应用程序时的内存泄漏,避免此问题的方法是清除(onDestroy();)此缓冲区。

于 2013-01-31T07:37:34.487 回答
3

一些提示:

  • 完成活动后回收位图(例如 onDestroy)
  • 尽可能使用应用程序上下文而不是活动本身作为上下文
于 2013-01-31T07:38:09.030 回答
1

尝试在您的活动的 onDestroy() 中回收()您的位图。

于 2013-01-31T07:37:13.617 回答
0

此处详细说明了您需要做的事情。对于您的具体问题,您需要这样做

// 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();
于 2013-01-31T07:51:49.743 回答