2013-02-03 128 views
8

所以我发现,与我保持每surfaceCreate如何解决涉及线程的Android内存泄漏?

我想我需要这些线程,虽然创建多个ThreadsMAT,但这种方法会导致的ViewThread多个实例,为用户浏览我的应用程序,这是内存泄漏。

如何重新组织我的线程创建和处理的方式,以防止发生这种情况,或者如何阻止泄漏发生?

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

我打开,从我的游戏Career活动导航走五次,这是对MAT

leak

编辑显示的内容:因为我已经发现,根据surfaceDestroyed为破坏我的线程是不可靠的。我现在从不同的方法调用相应的线程销毁调用,触发。

回答

4

您应该使用WeakReference来引用您的主题中的职业。这样,当没有更多的职业生涯的参考资料时,参考资料将被清除。

您可以通过右键单击职业并选择Path to GC Roots,然后选择所有参考来跟踪MAT中的所有参考。这将向您显示保存在内存中的对象的路径。确保在完成活动时清除这些引用,或者使用WeakReference使GC自动清除它们。

+0

我试过了,而那些多个实例我的班级依然堆积如山。 – Houseman

+0

在这种情况下,您可以使用MAT来查找从GC根到对象的路径。你可能会在监听器/观察者的某处找到另一个参考。这也可能是一个匿名的内部类。在这种情况下,尝试使用静态类,并在类的实例中使用弱引用。一旦gc运行,这将断开链接。您也可以尝试在适当的时候手动注销监听器。如果这不起作用,你可以分享MAT的屏幕截图,以显示GC根的路径吗? – nickmartens1980

1

里面surfaceDestroyed,你应该等待以确保线程在你返回之前停止。

你可以参考this question更多细节

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    boolean retry = true; 
    mThread.setRunning(false); 
    while (retry) { 
     try { 
      mThread.join(); 
      retry = false; 
     } catch (InterruptedException e) { 
     } 
    } 
} 
+0

我试过了,它似乎没有工作。查看转储时,我仍然看到了多个线程实例。 – Houseman

1

所以我通过注释一行固定它:

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    loading=false; 
    if (!mThread.isAlive()){ 
     //mThread = new ViewThread(this); 
     mThread.setMenuRunning(true); 
     mThread.start(); 
    } 
} 

这也与WeakReferenceSurfaceDestroyed答案相结合。 我稍后会对它进行测试,并确定它是否只是删除那一行,或者与那个和弱引用的组合,或者其他事情,然后授予答案

+0

这将是正确的。重要的是要注意原始思维中的缺陷。 isAlive()需要一个有效的对象引用,因此对于是否需要新的Thread对象来说不是一个好的指示器。如果您有一个不活动的有效线程,isAlive()将返回false ...因此,创建一个新的线程is!isAlive()将导致您描述的行为。决定是否添加新线程的唯一有效方法是检查空指针引用。无论如何,检查空指针是个好习惯:) –