4

Hello I am working out a game and I wonder how to dispose resources as I am experiencing memory problems.

I have something like this:

public SplashScreen implements Screen {
    @Override
    public void render(float delta) {
    }
    @Override
    public void dispose() {
        if (batch != null)
            batch.dispose();
        batch = null;
    }
}

public MapScreen implements Screen {
    @Override
    public void render(float delta) {
    }
    @Override
    public void show() {
        splashScreenInstance.dispose();
    }
    @Override
    public void dispose() {
        if (mesh != null)
        mesh.dispose();
        mesh = null;
    }
}

And I am disposing the splash screen as soon as the show method of MapScreen is called. Previously I'd settled the screen to the MapScree. Still the render method of the splashScreenInstance is called and I'd received null pointer exceptions. Why this is so?

I'd expect that once I set another screen, the previous one is no longer rendered. This is not seemingly so. I'd tried disposing right after setting the screen using the game instance, right after the hide method is called on the screen I want to dispose and finally on the show method of the next screen. All of these cases still renders the previous screen a few times before rendering the current one.

I really need to recover memory and also I don't want to test each time (On the render method) for null pointers as this has performance penalties.

Any suggestions?

Thanks

Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
Juan Chô
  • 542
  • 6
  • 23

2 Answers2

3

This is how I usually handle this problem:

public SplashScreen implements Screen {
    @Override
    public void render(float delta) {
        // I assume that you have a reference to the game somewhere to switch the screen
        game.setScreen(new MapScreen());
        dispose();
        return;
    }
}

I first set the new Screen, then dispose() the current one and then immediately stop any further execution of the current screen via return. This way the current render cycle should be stopped and in the next cycle the render() of your next screen will be called.

Another approach might be to call dispose() in your hide() method of the Screens, because that is going to be the last method being called before the Game will use the next screen. This is especially useful when there could be several different next screens. In that case there will still be only a single place of dispose() and that will be in the hide() method.

noone
  • 19,520
  • 5
  • 61
  • 76
  • Thanks noone, yea but this way you still need to put some logic into the render method. This logic is going to be called each FPS. Actually I have something similar, checking for null pointer and then rendering, but still logic inside render... I'd be glad if I can avoid that. – Juan Chô Mar 11 '14 at 18:45
  • 1
    You need some logic in the render method, because how else are you going to switch the screen if not from the render method? Furthermore this logic will not cause any less FPS. Maybe something like 0.0000001 FPS less or something in that range. – noone Mar 11 '14 at 19:44
  • Thanks noone, I am using a Listener, and hence missing a clean return. I am going to rewrite for handling the return. – Juan Chô Mar 12 '14 at 14:58
1

Where are you calling setScreen? Since everything should be happening in the rendering thread (even InputListeners) you should be able to call setScreen in your first Screen and then return from the render method. The Game instance will automatically call hide on your first Screen which is where you can call dispose.

Chase
  • 3,123
  • 1
  • 30
  • 35
  • Sometimes I am calling on render and sometimes on an applicationlistener. Perhaps I will dispose ans settle a boolean for avoiding rendering when disposed. Anyhow thanks for your hint. I am going to test. – Juan Chô Mar 12 '14 at 08:37