2013-02-03 198 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()將導致您描述的行爲。決定是否添加新線程的唯一有效方法是檢查空指針引用。無論如何,檢查空指針是個好習慣:) –