【问题标题】:Android memory leak between activities活动之间的Android内存泄漏
【发布时间】:2013-01-31 07:28:29
【问题描述】:

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

我有两个SurfaceViewsAB。我开始A,然后导航到B,然后按返回按钮返回到A,然后我再次导航到B

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

这是我从连接到ASurfaceView 内部导航到B 的方法

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

在这两种视图中,我都有很多位图绘图。在B 中,我找不到对A 的任何引用,而我能想到的上下文之外的唯一引用是对我拥有的全局类的引用。我还在后台进行了一些分析。我想这可能是一百万种不同的东西

我在 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);
    }
}

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

【问题讨论】:

  • 你有这些活动的位图吗?
  • 在与他们关联的SurfaceViews中,是的。
  • 粘贴该代码和你的 onDestroys
  • 这个 Global 类有什么作用?它是否包含对任何视图、可绘制对象、处理程序或类似内容的任何引用?静态变量呢?有许多常用对象将整个 Activity 上下文保存在内存中。
  • @Siddharth done @mkuech Global 类包含各种整数、字符串,哦,还有一个Resources,它是从A 的构造函数中设置的

标签: android memory-leaks


【解决方案1】:

在您的应用程序的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();
        }
 }

【讨论】:

  • 我将它添加到B,但它从未到达第二条日志语句
  • 能否请您添加一些解释代码的作用。
【解决方案2】:

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

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

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

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

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

【讨论】:

  • 我下载了这个,并运行了泄漏分析器,它给了我一个漂亮的小饼图,它并没有真正告诉我任何事情。可能是因为我还不知道如何使用它
  • 另外,您似乎从其他地方复制粘贴了这个答案。顶点缓冲区是怎么回事?
  • 嗯,你帮我缩小了范围,至少,这是最大的帮助。
  • 我发现的内存泄漏现在是它自己的问题:stackoverflow.com/questions/14677913/…
【解决方案3】:

一些提示:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 我会试试这个,但我不知道如何访问我创建的视图的成员
    • 你在你创建的 Bitmap 对象上调用 recycle(),比如:Bitmap rightB,leftB;就像 rightB.recycle();
    • 好吧,我尝试回收我在B 中绘制的所有三个位图,但似乎没有帮助。内存泄漏仍然发生。问题一定出在其他地方
    • 所以,我实现了这个,每当我退出我的应用程序并返回时,它就会崩溃,因为我试图绘制的位图被回收了。可能是因为位图是静态的。
    • 已知静态非平凡成员会泄漏上下文。我会在那里开始调查
    【解决方案5】:

    您需要做的是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();
    

    【讨论】:

    • 我有内存泄漏。我没有为位图分配太多内存
    • 无论分配多少内存,清理都是必不可少的。众所周知,位图在内存相对较少的情况下会很快导致 OOM。
    猜你喜欢
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多