简体   繁体   English

LibGdx RAM使用率持续增加

[英]LibGdx RAM usage continuously increases

I wrote these 3 classes to test them on android. 我编写了这3个类以在android上对其进行测试。 If I just press Menu button and hide the app, then open it again, then hide and reopen it again and again ram usage increases every time I hide the app. 如果我只按Menu(菜单)按钮并隐藏该应用程序,然后再次将其打开,然后再次隐藏并重新打开它,则每次我隐藏该应用程序时,ram的使用都会增加。

The same problem occurs if I just switch between classes inside the app, app uses more and more ram. 如果我只是在应用程序内部的类之间切换,则会发生相同的问题,应用程序使用的RAM越来越多。

I was looking for a solution of this problem here and I saw tutorials on yotube, but I have not found it. 我在这里寻找该问题的解决方案,并且在yotube上看到了教程,但没有找到。 I don't understand what can be wrong here. 我不明白这里可能出什么问题。

Can someone explain what am I doing wrong? 有人可以解释我在做什么错吗?

public class MyEF extends Game {

    @Override
    public void create() {

        setScreen(new TestScreen1(this));
    }

    @Override
    public void dispose() {
        super.dispose();
    }

    @Override
    public void render() {
        super.render();
    }

    @Override
    public void resize(int width, int height) {
        super.resize(width, height);
    }

    @Override
    public void pause() {
        super.pause();
    }

    @Override
    public void resume() {
        super.resume();
    }

}

// TEST1
public class TestScreen1 implements Screen {

    private MyEF game;

    public TestScreen1(MyEF game) {
        this.game = game;
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if(Gdx.input.justTouched()){
            game.setScreen(new TestScreen2(game));
            dispose();
            System.out.println("TOUCHED ");
        }

    }

    @Override
    public void show() {
    }

    @Override
    public void dispose() {
        game.dispose();
    }

    @Override
    public void hide() {
    }
    @Override
    public void pause() {
    }
    @Override
    public void resume() {
    }
    @Override
    public void resize(int width, int height) {
    }
}

// TEST2
public class TestScreen2 implements Screen {

    private MyEF game;

    public TestScreen2(MyEF game) {
        this.game = game;
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if(Gdx.input.justTouched()){
            game.setScreen(new TestScreen1(game));
            dispose();
            System.out.println("TOUCHED ");
        }

    }

    @Override
    public void show() {
    }

    @Override
    public void dispose() {
        game.dispose();
    }

    @Override
    public void hide() {
    }
    @Override
    public void pause() {
    }
    @Override
    public void resume() {
    }
    @Override
    public void resize(int width, int height) {
    }
}

I'd not have any static Screens because of this. 因此,我没有任何静态Screens "Resetting" screens will introduce bugs and not very well maintainable code. “重置”屏幕将引入错误,并且代码的可维护性也不太好。 It is easier in many cases to just create a new "clean" screen. 在许多情况下,仅创建一个新的“干净”屏幕会更容易。

Also you are describing an effect here. 您也在这里描述一种效果 Not a problem . 问题 Yes the memory usage increases. 是的,内存使用量增加了。 But is it a problem? 但这有问题吗? No! 没有! Why not? 为什么不? Because the user won't send the app to the background and restart it 1000 times in a row. 因为用户不会将应用发送到后台并连续重新启动它1000次。 And even if he does, the memory usage will not grow endlessly. 即使他这样做,内存使用量也不会无限增长。 It keeps growing because the amount of memory which gets added is so small that the JVM does not even invoke the garbage collector. 它一直在增长,因为要添加的内存量非常小,以至于JVM甚至不调用垃圾回收器。

After enough iterations of resuming the app, the garbage collector will eventually kick in and clean up all your unused screens. 在恢复应用程序足够的迭代之后,垃圾收集器最终将启动并清理所有未使用的屏幕。

In general you should not change your architecture now, based on this behaviour. 通常,您不应基于此行为立即更改体系结构。 As a rule of thumb you can always instantiate new objects, for example when switching screens, or when doing things only once. 根据经验,您总是可以实例化新对象,例如在切换屏幕或仅执行一次操作时。 The user will not be bothered if the garbage collector kicks in in a loading screen, or when the game just started. 如果垃圾收集器在加载屏幕中启动,或者游戏刚开始,用户将不会受到困扰。 You should only be concerned when doing it in the render() method, because then the garbage collector might clean up while the actual gameplay and may cause lags. 您只需要在render()方法中执行此操作即可,因为垃圾收集器可能会在实际游戏过程中清理并可能导致滞后。

Stuntmania is correct. 特技演员是正确的。 Creating new objects = increased RAM usage, especially when you do it during the render() method. 创建新对象=增加RAM使用率, 尤其是render()方法期间执行此操作时。 In game development in general, and LibGDX in particular, you should always question your usage of the new keyword. 通常,在游戏开发中,尤其是在LibGDX中,您应该始终质疑您对new关键字的使用。 Make things static wherever possible. 尽可能使事情静止。

Specifically, your main game class should do something like this: 具体来说,您的主要游戏类应该做这样的事情:

public class MyEF extends Game {
    public static TestScreen1 myScreen1;
    public static TestScreen2 myScreen2;

    @Override
    public static void create() {
        myScreen1 = new TestScreen1(this);
        myScreen2 = new TestScreen2(this);
        setScreen(myScreen1);
    }

    (...)
}

Then, in your render() method for each of the screens, you would simply call game.setScreen(myScreen2) . 然后,在每个屏幕的render()方法中,只需调用game.setScreen(myScreen2) This way, you are no longer creating new objects during each render cycle. 这样,您将不再在每个渲染周期内创建新对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM