在桌面上使用Libgdx,如何处理窗口关闭时的资源释放问题

5
我正在使用libgdx(com.badlogic.gdx.Game和Screens等)制作游戏。我有以下问题:在桌面上,当我关闭窗口(从顶部的叉号)时,应用程序会关闭。但是我想回到菜单屏幕并在那里处理资源的disposing(通过asset manager)。我在游戏中有退出按钮,如果以这种方式退出,那很好。问题是红色的叉可以被按下。那么我该如何正确处理disposing?
在安卓版本中,我捕获了返回键,并以自己的方式处理离开游戏的不同部分和整个游戏。在那里它运行良好。
我还有一个相关的问题:
在桌面上,应用程序无法像安卓版本一样自动停止然后dispose(没有用户明确退出),对吧?所以,如果我在暂停()上进行临时保存并在恢复()上从其中恢复游戏状态,这是一个好主意吗?由于恢复不是完全恢复,而且我不希望在桌面上最小化窗口时发生恢复(我注意到,在最小化/恢复窗口时调用pause()/resume())。

抱歉,我没有理解您的问题。您是如何实现dispose方法的? - donfuxx
在游戏屏幕的dispose()方法中,我保存了游戏并且释放了其中的阶段。但问题是,当从退出按钮(在桌面上)关闭应用程序时,它永远不会返回到菜单屏幕,并且资源不会被释放(我在菜单屏幕的dispose()方法中进行资源释放)。 - ploosu2
4个回答

4
我建议使用libgdx生命周期方法
要进行处理,您应该使用dispose()方法。您不需要自己调用dispose!当应用程序被销毁时,它将被自动调用,请参见文档:

dispose()在应用程序被销毁时调用。它之前会调用pause()。

因此,只需在您的屏幕中实现dispose方法即可:
@Override
public void dispose () { 
    //your code needs to get added here, like for example:
    stage.dispose();
    texture.dispose();
    //etc..
}

更新:请注意,AppliacationListener的dispose()方法会被自动调用,而不是Screen的dispose()方法。请参见Springrbua的评论。

我认为当应用程序被销毁时,只有Game的dispose方法被调用,默认情况下它只会在当前屏幕上调用hide()方法。因此,屏幕不会自动被处理掉。 - ploosu2
是的,当应用程序被销毁时,将调用dispose方法。但是正如您所看到的,默认实现并没有做太多事情。这就是为什么_您_必须在那里添加处理代码的原因。 - donfuxx
2
Screen 的文档说明,Screendispose() 方法不会自动调用。因此,在 hide() 方法中需要手动调用 dispose() 方法,或者在你的 Game / ApplicationListenerdispose() 方法中调用 screen.dispose() - Robert P
1
返回翻译后的文本:true。 - donfuxx

3

您可以通过在游戏类的dispose()中显式调用来调用dispose()以释放屏幕资源,如下所示:

MyScreen类:

public class MyScreen implements Screen {
    // Not going to write all other methods that need to be overridden

    @Override
    public void dispose() {
        // Clear you Screen Resources here
    }

}

MyGame 类:

public class MyGame extends Game {
    // Not going to write all other methods that need to be overridden

    @Override
    public void create() {
        setScreen(new MyScreen());

    }

    @Override
    public void dispose() {
        // Clear you Screen Explicitly
        getScreen().dispose();

    }
}

希望这可以帮助您。

1

如上所述,Screen 接口包含一个 dispose 方法。此外,可以重写 Gamedispose 方法以自动处理当前屏幕的清除。但是,这并不是默认设置的原因。假设您有多个 Screen - Screen1Screen2。屏幕1处于活动状态,然后将屏幕更改为2。然后退出游戏,调用 dispose 方法,该方法调用 当前 屏幕的 dispose 方法 - 使屏幕1保持不变。

我喜欢的方法是通过重写 setScreen 方法并添加 Screen[] screens、boolean[] scrDiss 和索引来跟踪游戏设置的屏幕。当对 Game 进行 dispose 调用时,它会检查所有已设置的屏幕,检查是否先前已 dispose 并进行处理。此外,Screen dispose 方法应该调用 Game 上的一个方法,在数组中查找它并标记为 disposed。这样,屏幕可以在游戏结束之前被清除,但当游戏被 dispose 时,所有屏幕也都会被清除。


0

当您的应用程序被处理时,请对所有屏幕调用dispose。


谢谢你的回答。我应该在我的游戏类中保留对所有屏幕的引用吗?现在我只有对菜单屏幕的引用。但是我怎么知道屏幕是否已经被处理掉了呢?我应该在屏幕类中引入一个布尔值isDisposed吗? - ploosu2
现在我明白了:我不应该在自己的exitGame()方法中调用dispose(),因为Game的dispose会处理它。我想我必须添加对我拥有的所有屏幕的引用,并检查它们是否不为空并将其dispose。如果我提前dispose它们,那么我在Game中的引用就会变成null。这听起来像一个好主意吗? - ploosu2
你应该实现dispose()方法。请查看文档:https://github.com/libgdx/libgdx/wiki/The-life-cycle @ploosu2 - donfuxx
是的,我现在已经实现了它。 (默认版本只调用当前屏幕上的hide(),我之前也使用过它来决定是否dispose()。)顺便说一句,我从链接中读到resume()只在Android上调用。不过,我的桌面版本在最小化屏幕时调用pause(),在恢复时调用resume()。这只是某种调试问题还是什么? - ploosu2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接