由于内存不足(在程序中,而不是在程序员中),我一直在使应用程序崩溃。 MAT表明,有时我的Activity的副本有时会在屏幕旋转时保留下来,而使伪副本仍然有效的唯一对象是每个实例的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个方向之后,MAT会列出net.catplace.tts_leak.MainActivity的一到八个实例,以及各种TTS对象的多个实例。例如:
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表示TTS正在保留MainActivity的伪造副本:
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
---------------------------------------------------------------------------------------------------------------------
我在各种实际设备和AVD中都表现出这种行为。以上结果来自Nexus 7。
我尝试了不同的TTS引擎,使用不同的事件来创建和销毁mTts等。
我的假设是TextToSpeech并不总是将其对创建它的上下文的引用为空,从而导致上下文(Activity)的副本泄漏。但是我是新来的。我做错了什么吗?
最佳答案
查看TextToSpeech here的源代码,您会注意到它实际上将服务绑定(bind)到传递的上下文,并且shutdown方法实际上将其解除绑定(bind)。现在可以猜测一下,由于Service有其自己的生命周期,因此TextToSpeech可能会限制上下文。如果您进行了一些研究并牢记您实际上正在运行服务,则可能会破解这个问题。
现在我也不确定这意味着什么,但是我愿意接受您方面的任何新发现。
鉴于TextToSpeech是一项服务,您可能希望将其传递给应用程序上下文,因为当 Activity 被销毁时,该服务仍将运行。
Also for further reading ______________
关于android - TextToSpeech和内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19653223/