libgdx/assets What counts as “non static”?

2019-08-23 03:08发布

问题:

Recently i have been working to get some libgdx projects working on Android. I have read that AssetManager should never be declared static as this causes issues on pause/resume.

But what exactly can you get away with?

public  AssetManager assetsmanager;
static public  AssetManager assets;

private void setup() {

    assetsmanager = new AssetManager();
    assets=assetsmanager;
    ....

seems to easy ?

回答1:

If you don't make it static, then you have to do one of two things:

  1. Create the AssetManager and then pass a reference of it between your screens

OR

  1. Create a new AssetManager each screen and load it up with only the relevant assets for each screen when the screen is created.

I prefer to create one AssetManager in your main class and load all assets. Pass reference of your Main class to other screen so that I can access assetmanager there.

public class Main extends Game {

   public AssetManager assetManager;  // for loading all assets

   @Override
   public void create(){
        assetManager = new AssetManager();
        assetManager.load("assets/data/yourSkin", Skin.class);
        assetManager.finishLoading();  // load assets (not asynchron for this example)
        setScreen(new GameScreen(this));
   }

   @Override
   public void dispose() {
      assetManager.dispose();   // disposes all assets when the game exits
   }
}

Gdx.app.getApplicationListener() return ApplicationListener instance. so you can typecast to your implemented class and then easily access any method or data member of that class.

In this way :

((Main)Gdx.app.getApplicationListener()).assetManager  // <-- You can use from where you want


回答2:

It is actually OK to have a static reference to assets, but this is discouraged because the vast majority of new users don't understand the Android application life cycle well enough to do it without creating memory leaks or missing "loaded" assets. There are very frequent questions on here and the LibGDX forums where some bug has been caused by incorrect use of static references. (But if your app has a live wallpapers, static references definitely cannot be used because there can be simultaneous LibGDX service instances running due to the live wallpaper preview.)

The code you posted is irrelevant because there is not enough context there to see if you're doing something incorrectly.

I argue that static references should be avoided anyway, because they can create error-prone code that is difficult to debug. Usually, the only reason people want to use them is to avoid a little bit of typing to pass the object reference around. Not a justifiable reason, in my opinion. It will cost you much more time in bug-hunting than you save in typing.

The primary problem with static references to assets is this:

  1. Many asset types (textures, shader programs, meshes) use native (JNI) memory that is not automatically cleaned up by the garbage collector.
  2. An Android Application can have multiple Activities that run in the same application process. If you close your game by backing out of an Activity, then usually when you open the game again, a new Activity is running in the same Application process, so the static references from the previous session are still held.

The most typical mistakes people seem to make is using a singleton for an asset or the SpriteBatch (which also contains some native memory objects). The singleton pattern typically lazy-loads the object. So if a game is closed and re-opened, the asset(s) doesn't get reloaded and will cause visual bugs, as well as leaking the asset memory from the previously loaded Activity. However, the singleton pattern can be adapted by properly disposing of all assets in the dispose() method and nulling out the static reference so a new object will be loaded the next time the game is opened. Care must be taken to not access the singleton object after dispose() is called on it.