[SOLVED] Create AppState - is singleton required?

I don’t want to create instances of my AppStates on startup so I created “AppStateSwitcher” AppState that will manage creation, attaching and detaching AppStates for me…

Code for most important part looks like this:

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
        if (name.equals("Toggle World Settings") && keyPressed && !stateManager.hasState(appState_world_settings)) {
            appState_world_settings = new AppState_World_Settings(main);
            stateManager.attach(appState_world_settings);
            if (stateManager.hasState(appState_world_settings)) { //DEBUG
                System.out.println("World Settings Attached"); //DEBUG
            }
        }
        if (name.equals("Toggle World Settings") && keyPressed && appState_world_settings.isInitialized()) {
            stateManager.detach(appState_world_settings);
            if (!stateManager.hasState(appState_world_settings)) { //DEBUG
                System.out.println("World Settings Detached"); //DEBUG
            }
        }

As You see I’m creating instance of AppState_World_Settings on F1 click. The question is: If I click F1 repeatedly will I create several instances of it or will it be the same instance all the time? Obviously I’d like to avoid having 9999 instances with same name wasting my resources.

And second thing: when instead of && appState_world_settings.isInitialized() in my code I had && stateManager.hasState(appState_world_settings) my F1 attached and detached AppState at the same time. Why? Logically both !has... and has... can’t be true at the same time.

Perhaps this code can help, since apparently you have appState_world_settings as a variable in your class

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
        if (name.equals("Toggle World Settings") && keyPressed) {
            if(null == appState_world_settings){
                appState_world_settings = new AppState_World_Settings(main);
                stateManager.attach(appState_world_settings);
            }else{
                appState_world_settings.cleanup(); //This helps and use it well :)
                stateManager.detach(appState_world_settings);
                appState_world_settings = null;
            }
        }
  • Yes I have it as variable - makes it so much simpler to call by name whenever I want.

  • If I understood correctly MyAppState.cleanup() is called automatically when I do detach(MyAppState). And I have cleanup() function in my AppStates anyway because I need to detach some nodes, lights, etc.

  • What I don’t know though is if creating another instance of MyAppState with exactly same name overwrites previous instance or creates another one (thus stains my resources). Tutorials say that only one instance of same AppState at a time can be attached, they don’t say anything if only one instance of same AppState at a time can be created…

  • So in simpler words: What happens when I do myappstate = new MyAppState after I did it already before and only detached.

You just created a new instance of MyAppState assiged to myappstate, You lost the pointer to the one you had before.

If you only need one instance, I think you can use this, then only use new once. and check if its attached or detached, and do not implement the cleanup code, just make your own cleaning method that you can call manually.

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
        if (name.equals("Toggle World Settings") && keyPressed) {
            if(!stateManager.hasState(appState_world_settings)){
                if(null == appState_world_settings){
                    appState_world_settings = new AppState_World_Settings(main);
                }
                stateManager.attach(appState_world_settings);
            }else{
                stateManager.detach(appState_world_settings);
            }
        }

Exactly - I lost the pointer. So previous instance is just empty 0’s and 1’s flying somewhere… Can I trust that Java Garbage Collector will take care of this?

And Yes I know how to make it happen (what You gave me is more or less singleton - “check if instance exists and create new one only if it doesn’t or else use the one already existing”) but I want to know if I even need to such stuff? :smile:

You could call it be a pseudo singleton, but I rather just think of it as a single instance variable since Singleton has a lot more features and practical uses. :wink:

You can trust the garbage collector to a certain degree, but you have to cleanup the previous instance in MyAppState properly to make the job a bit easier and avoid possible referencing errors in your code.

1 Like