我遇到了一个非常奇怪的现象(测试设备:HTC Desire HD,Android 2.3.5)。我知道 System.gc()
是不必要的和不鼓励的,我不会尝试提出其他建议,但重点是它也不应该引起问题(即它至多应该是无用的)。
我有一个应用程序,在其 View 层次结构中包含一个 GLSurfaceView
。 GLSurfaceView
被实例化并添加到 Activity.onCreate()
中。通常,应用程序是这样工作的:
- 用户启动应用程序并转到主菜单
- 用户选择一个主菜单项,将
GLSurfaceView
设置为View.VISIBLE
- 用户在
GLSurfaceView
上玩内置游戏 - 用户转到主菜单并退出 Activity (=>
Activity.finish()
被调用)
我的 Activity.onPause()
看起来像这样:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
到目前为止一切顺利,一切正常。但是,在我将以下代码添加到 onPause()
后出现问题(针对用户从主菜单退出游戏的情况):
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
if (isFinishing()) {
System.gc();
}
详细信息:如果 Activity
第一次 启动(= 即应用进程之前不存在),一切正常。但是,从 Activity 的第二次开始开始(= 在第一次退出主菜单之后,即在第一个 Activity.finish()
之后),帧速率GLSurfaceView 减少了 40-50%,内置游戏变慢了。
如果我删除 System.gc()
调用,问题就会消失。此外,如果我执行以下操作,它也可以解决问题:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
if (isFinishing()) {
// 1. get layout root of View hierarchy
// 2. recursively remove (detach) all Views
// 3. call GC
System.gc();
}
我没有添加具体的代码,因为它很复杂,所以我使用了注释。如果我只是通过 removeView()
分离 GLSurfaceView
,这是不够的。需要清除整个 View 层次结构。
请注意,我找不到任何内存泄漏(没有通过可绘制对象/静态等发生的 Activity 泄漏)。此外,当然,当应用程序关闭时,gameThread 会正确退出(我只是没有包含它的源代码)。
任何想法,猜测?显然,System.gc()
似乎对 Android 的 Activity/layout 破坏机制造成了一些问题。同样,正如我所说,如果我删除 System.gc()
,问题就会消失。
最佳答案
我有 Android 游戏编程经验。我过去常常清除层次结构中的所有 View ,因为在运行线程时,如果您调用 System.gc() 有时会发生您的线程引用了您的某些 View ,即使您调用 system.gc() 此 View 也不会被移除,如果您一次又一次地玩这个游戏,您会注意到您的堆内存开始增长。
这取决于内存泄漏,如果您泄漏了一些 KB 内存,则需要更多时间才能使您的游戏崩溃。最好的方法是使用 Eclipse Memory Anlyser (Eclipse MAT) 并比较您的堆栈。
第一步: 第一次开始游戏时拍摄内存快照 第二步: 第二次开始游戏时拍摄内存快照 第三步: 现在比较你的两个快照堆栈,它会告诉你不同之处。
这是一个非常有用的工具。我在游戏中遇到了巨大的内存问题 Apache Attack .我使用这个很棒的工具修复了它们。 关注这个ECLIPSE MAT TUTORIAL
关于android - System.gc() 导致从 Activity 的第二次启动开始变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11601914/