2013-10-29 111 views
2

由於內存不足(在程序中,而不是程序員),我一直在發生應用程序崩潰。 MAT表明,我的Activity的副本有時會在屏幕旋轉中保留,唯一保留僞造副本的對象是每個實例的TextToSpeech對象。我可以用這個片段複製此行爲:取向的變化TextToSpeech和內存泄漏

public class MainActivity extends Activity { 
    TextToSpeech mTts; 
    char[]   mBigChunk = new char[1000000]; // not used; just makes MainActivity instances easier to see in MAT 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 
    @Override 
    public void onStart() { 
     super.onStart(); 
     if (mTts==null)        // shouldn't be necessary and doesn't make any difference 
      mTts = new TextToSpeech(this, null);  // commenting this out fixes the leak 
    } 
    @Override 
    public void onStop() { 
     super.onStop(); 
     if (mTts != null) { 
      mTts.shutdown(); 
      mTts = null;  // shouldn't be necessary and doesn't make any difference 
     } 
    } 
} 

30後,一個和net.catplace.tts_leak.MainActivity的八個實例,以及各種TTS對象的多個實例之間MAT名單;例如:

Class Name               | Shallow Heap | Retained Heap | Percentage 
------------------------------------------------------------------------------------------------------------------ 
android.speech.*              |    |    |   
android.speech.tts.TextToSpeech$Connection$1 @ 0x42de94c8 Native Stack|   24 |  2,052,664 |  11.85% 
android.speech.tts.TextToSpeech$Connection$1 @ 0x431dd500 Native Stack|   24 |  2,052,664 |  11.85% 
android.speech.tts.TextToSpeech$Connection$1 @ 0x435cc438 Native Stack|   24 |   552 |  0.00% 
android.speech.tts.TextToSpeech$Connection @ 0x441b3698    |   32 |   528 |  0.00% 
android.speech.tts.TextToSpeech @ 0x43fb3c00       |   64 |   496 |  0.00% 
android.speech.tts.TextToSpeech$Connection @ 0x43fb4420    |   32 |   48 |  0.00% 
android.speech.tts.TextToSpeech$Connection$1 @ 0x43fb4440 Native Stack|   24 |   24 |  0.00% 
android.speech.tts.TextToSpeech$Connection$1 @ 0x441b36b8 Native Stack|   24 |   24 |  0.00% 
Total: 8 entries (13,079 filtered)         |    |    |   
------------------------------------------------------------------------------------------------------------------ 

MAT表示MainActivity的虛假副本被保留TTS:

Class Name                   | Shallow Heap | Retained Heap 
--------------------------------------------------------------------------------------------------------------------- 
                         |    |    
net.catplace.tts_leak.MainActivity @ 0x437c6068          |   200 |  2,001,352 
'- mContext android.speech.tts.TextToSpeech @ 0x431de6d8        |   64 |   496 
    '- this$0 android.speech.tts.TextToSpeech$Connection @ 0x441b3698     |   32 |   528 
     '- this$1 android.speech.tts.TextToSpeech$Connection$1 @ 0x441b36b8 Native Stack|   24 |   24 
--------------------------------------------------------------------------------------------------------------------- 

我在一系列真實設備和自動真空澱積的得到這個水煤漿。上述結果是從的Nexus 7

我已經嘗試了不同的TTS引擎,使用不同的事件來創建和銷燬MTTS等

我的假設是,文字轉語音並不總是空的參考創建它的上下文,導致上下文(Activity)的泄露副本。但我是新來的;有什麼我做錯了嗎?

+1

如果文字轉語音對象通過使構成'getApplicationContext()'而不是'this'(活動),問題似乎沒有發生。這種方法很有意義,因爲應用程序在方向更改時不會被破壞。然而,應該沒有必要這樣做。 –

+0

我有同樣的問題。屏幕旋轉導致我的活動被泄漏。在內存中旋轉10次,10次活動。我改變它將getApplicationContext()傳遞給TextToSpeech對象,而不是像Peter建議的那樣傳遞給TextToSpeech對象,並解決了問題。繁榮! –

回答

0

如果沒有implemtned android:configChanges="orientation",那麼你可以重寫onDestory方法:

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    if (ttsEngine != null) { 
     ttsEngine.stop(); 
     ttsEngine.shutdown(); 
     Log.d(TAG, "TTS destroyed"); 
    } 
} 
+1

試過了。它仍然泄漏(有時)。 –

0

考慮看看文字轉語音here的源代碼,你會發現,它實際上綁定服務,通過上下文和關機方法實際上解除了綁定。現在剩下的就是猜測,因爲Service有自己的生命週期,TextToSpeech可能會阻礙上下文。如果您在研究中記住了您實際上在運行服務,那麼您可能會解決這個問題。

現在我不確定這可能意味着什麼,但我願意接受來自你方的任何新發現。 鑑於TextToSpeech是一種服務,您可能希望將它傳遞給應用程序上下文,因爲服務在活動被破壞時仍然會運行。

Also for further reading ______________

+1

再次感謝。我注意到,傳遞應用程序上下文似乎使問題消失。這是一個恥辱谷歌的例子使用活動的上下文。你的第二個鏈接表明該服務試圖做出聰明(和異步)的事情,這可以解釋我注意到的不一致的內存泄漏行爲。這可能取決於取向變化發生的速度。 –

+0

http://stackoverflow.com/questions/7298731/when-to-call-activity-context-or-application-context...閱讀「commonsware」的答案,雖然沒有直接關係到討論的話題,但它可以很好地瞭解什麼時候使用什麼上下文。 –

+0

很棒的發現。我認爲它可以**直接相關,因爲它說使用應用程序上下文服務(TTS,正如你之前指出的那樣)。谷歌的相反例子看起來是令人鼓舞的泄露。 –