Android 调用SharedReferences会使我的应用程序在onManagedUpdate中崩溃

Android 调用SharedReferences会使我的应用程序在onManagedUpdate中崩溃,android,sharedpreferences,andengine,Android,Sharedpreferences,Andengine,我的sharedprefs类称为UserData mNPCSprite = new MyAnimatedSprite(310, 35, AssetLoaderUtil.mPlayerTextureRegion, mContext) { @Override protected void onManagedUpdate(float pSecondsElapsed) { super.onManagedUpdate(

我的sharedprefs类称为UserData

mNPCSprite = new MyAnimatedSprite(310, 35,
            AssetLoaderUtil.mPlayerTextureRegion, mContext) {

         @Override
        protected void onManagedUpdate(float pSecondsElapsed) {
              super.onManagedUpdate(pSecondsElapsed);

            if (mPlayerSprite.collidesWith(this)) {

                mCurrentPlayerHealth -= 1;


            //This call to UserData to add Gold, Crashes the app upon calling it.
            //
            //Leaving this line uncommented will crash app when i touch the NPC. \/\/\/

             UserData.getInstance().addPlayerGold(15);

             //yet, this toast, which gets a value from UserData, works fine \/\/\/

                mContext.toastOnUIThread("Welcome to map1, Gold in UserData: "
                        + UserData.getInstance().getPlayerGold(),
                        Toast.LENGTH_LONG);


                // this.setIgnoreUpdate(true);
            }
        }



    };

    mNPCSprite.setZIndex(10);
    this.attachChild(mNPCSprite);
我可以为我的HUD调用int,它工作正常,就像这样

Text levelText = new Text(0, 40, AssetLoaderUtil.mFontMENU, "LEVEL: "
            + UserData.getInstance().getMaxUnlockedLevel(),
            mContext.getVertexBufferObjectManager()){

        @Override
        protected void onManagedUpdate(float pSecondsElapsed) {
            super.onManagedUpdate(pSecondsElapsed);

           //This call to UserData works \/\/\/

            this.setText("LEVEL: " + UserData.getInstance().getMaxUnlockedLevel());

        }

    };
但在同一个类中,这将导致应用程序崩溃,因为需要在UserData中添加到playerGold

mNPCSprite = new MyAnimatedSprite(310, 35,
            AssetLoaderUtil.mPlayerTextureRegion, mContext) {

         @Override
        protected void onManagedUpdate(float pSecondsElapsed) {
              super.onManagedUpdate(pSecondsElapsed);

            if (mPlayerSprite.collidesWith(this)) {

                mCurrentPlayerHealth -= 1;


            //This call to UserData to add Gold, Crashes the app upon calling it.
            //
            //Leaving this line uncommented will crash app when i touch the NPC. \/\/\/

             UserData.getInstance().addPlayerGold(15);

             //yet, this toast, which gets a value from UserData, works fine \/\/\/

                mContext.toastOnUIThread("Welcome to map1, Gold in UserData: "
                        + UserData.getInstance().getPlayerGold(),
                        Toast.LENGTH_LONG);


                // this.setIgnoreUpdate(true);
            }
        }



    };

    mNPCSprite.setZIndex(10);
    this.attachChild(mNPCSprite);
/////////////////// 用户数据 //////////////////

package WorldScene.test.test;

import android.content.Context;
import android.content.SharedPreferences;

public class UserData {

private static UserData INSTANCE;

// Include a 'filename' for our shared preferences
private static final String PREFS_NAME = "GAME_USERDATA";

/* These keys will tell the shared preferences editor which
   data we're trying to access */

private static final String UNLOCKED_LEVEL_KEY = "unlockedLevels";

private static final String EXP_KEY = "playerExp";


private static final String SOUND_KEY = "soundKey";

private static final String PLAYER_GOLD = "playerGold";

/* Create our shared preferences object & editor which will
   be used to save and load data */
private SharedPreferences mSettings;
private SharedPreferences.Editor mEditor;

// keep track of our max unlocked level
private int mUnlockedLevels;

// keep track of our max unlocked level
private int mPlayerExp;

// keep track of whether or not sound is enabled
private boolean mSoundEnabled;

// keep track of whether or not sound is enabled
private int mPlayerGold;

UserData() {
    // The constructor is of no use to us
}

public synchronized static UserData getInstance() {
    if(INSTANCE == null){
        INSTANCE = new UserData();
    }
    return INSTANCE;
}

public synchronized void init(Context pContext) {
    if (mSettings == null) {
        /* Retrieve our shared preference file, or if it's not yet
         * created (first application execution) then create it now
         */
        mSettings = pContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

        /* Define the editor, used to store data to our preference file
         */
        mEditor = mSettings.edit();

        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mUnlockedLevels = mSettings.getInt(UNLOCKED_LEVEL_KEY, 1);

        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mPlayerGold = mSettings.getInt(PLAYER_GOLD, 0);


        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mPlayerExp = mSettings.getInt(EXP_KEY, 1);


        /* Same idea as above, except we'll set the sound boolean to true
         * if the setting does not currently exist
         */
        mSoundEnabled = mSettings.getBoolean(SOUND_KEY, true);
    }
}

/* retrieve the max unlocked level value */
public synchronized int getMaxUnlockedLevel() {
    return mUnlockedLevels;
}

/* retrieve the max unlocked level value */
public synchronized int getPlayerGold() {
    return mPlayerGold;
}

/* retrieve the max unlocked level value */
public synchronized int getPlayerExp() {
    return mPlayerExp;
}


/* retrieve the boolean defining whether sound is muted or not */
public synchronized boolean isSoundMuted() {
    return mSoundEnabled;
}

/* This method provides a means to increase the max unlocked level
 * by a value of 1. unlockNextLevel would be called if a player
 * defeats the current maximum unlocked level
 */
public synchronized void unlockNextLevel() {
    // Increase the max level by 1
    mUnlockedLevels++;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(UNLOCKED_LEVEL_KEY, mUnlockedLevels);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}


/* This method provides a means to increase the max unlocked level
 * by a value of 1. unlockNextLevel would be called if a player
 * defeats the current maximum unlocked level
 */
public synchronized void addPlayerGold(int g) {
    // Increase the max level by 1
    mPlayerGold += g;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(PLAYER_GOLD, mPlayerGold);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}

public synchronized void addPlayerExp(int x) {
    // Increase the max level by 1
    mPlayerExp += x;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(EXP_KEY, mPlayerExp);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}



/* The setSoundMuted method uses the same idea for storing new data
 * into the shared preferences. First, we overwrite the mSoundEnabled
 * boolean, use the putBoolean method to store the data, and finally
 * commit the data to the shared preferences
 */
public synchronized void setSoundMuted(final boolean pEnableSound) {
    mSoundEnabled = pEnableSound;
    mEditor.putBoolean(SOUND_KEY, mSoundEnabled);
    mEditor.commit();
}
 10-02 15:47:22.212: W/dalvikvm(848): threadid=11: thread exiting with uncaught exception (group=0x40fea2a0)
    10-02 15:47:22.235: E/AndroidRuntime(848): FATAL EXCEPTION: UpdateThread
    10-02 15:47:22.235: E/AndroidRuntime(848): java.lang.NullPointerException
    10-02 15:47:22.235: E/AndroidRuntime(848):  at WorldScene.test.test.UserData.addPlayerGold(UserData.java:143)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at Scene.WorldScene$1.onManagedUpdate(WorldScene.java:115)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.scene.Scene.onManagedUpdate(Scene.java:284)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onUpdateScene(Engine.java:604)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onUpdate(Engine.java:599)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.LimitedFPSEngine.onUpdate(LimitedFPSEngine.java:51)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onTickUpdate(Engine.java:561)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine$UpdateThread.run(Engine.java:833)
    10-02 15:47:22.251: W/ActivityManager(470):   Force finishing activity WorldScene.test.test/.WorldActivity
}

//////////// LogCat //////////

package WorldScene.test.test;

import android.content.Context;
import android.content.SharedPreferences;

public class UserData {

private static UserData INSTANCE;

// Include a 'filename' for our shared preferences
private static final String PREFS_NAME = "GAME_USERDATA";

/* These keys will tell the shared preferences editor which
   data we're trying to access */

private static final String UNLOCKED_LEVEL_KEY = "unlockedLevels";

private static final String EXP_KEY = "playerExp";


private static final String SOUND_KEY = "soundKey";

private static final String PLAYER_GOLD = "playerGold";

/* Create our shared preferences object & editor which will
   be used to save and load data */
private SharedPreferences mSettings;
private SharedPreferences.Editor mEditor;

// keep track of our max unlocked level
private int mUnlockedLevels;

// keep track of our max unlocked level
private int mPlayerExp;

// keep track of whether or not sound is enabled
private boolean mSoundEnabled;

// keep track of whether or not sound is enabled
private int mPlayerGold;

UserData() {
    // The constructor is of no use to us
}

public synchronized static UserData getInstance() {
    if(INSTANCE == null){
        INSTANCE = new UserData();
    }
    return INSTANCE;
}

public synchronized void init(Context pContext) {
    if (mSettings == null) {
        /* Retrieve our shared preference file, or if it's not yet
         * created (first application execution) then create it now
         */
        mSettings = pContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

        /* Define the editor, used to store data to our preference file
         */
        mEditor = mSettings.edit();

        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mUnlockedLevels = mSettings.getInt(UNLOCKED_LEVEL_KEY, 1);

        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mPlayerGold = mSettings.getInt(PLAYER_GOLD, 0);


        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
         * does not currently exist in our shared preferences, we'll create
         * the data to unlock level 1 by default
         */
        mPlayerExp = mSettings.getInt(EXP_KEY, 1);


        /* Same idea as above, except we'll set the sound boolean to true
         * if the setting does not currently exist
         */
        mSoundEnabled = mSettings.getBoolean(SOUND_KEY, true);
    }
}

/* retrieve the max unlocked level value */
public synchronized int getMaxUnlockedLevel() {
    return mUnlockedLevels;
}

/* retrieve the max unlocked level value */
public synchronized int getPlayerGold() {
    return mPlayerGold;
}

/* retrieve the max unlocked level value */
public synchronized int getPlayerExp() {
    return mPlayerExp;
}


/* retrieve the boolean defining whether sound is muted or not */
public synchronized boolean isSoundMuted() {
    return mSoundEnabled;
}

/* This method provides a means to increase the max unlocked level
 * by a value of 1. unlockNextLevel would be called if a player
 * defeats the current maximum unlocked level
 */
public synchronized void unlockNextLevel() {
    // Increase the max level by 1
    mUnlockedLevels++;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(UNLOCKED_LEVEL_KEY, mUnlockedLevels);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}


/* This method provides a means to increase the max unlocked level
 * by a value of 1. unlockNextLevel would be called if a player
 * defeats the current maximum unlocked level
 */
public synchronized void addPlayerGold(int g) {
    // Increase the max level by 1
    mPlayerGold += g;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(PLAYER_GOLD, mPlayerGold);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}

public synchronized void addPlayerExp(int x) {
    // Increase the max level by 1
    mPlayerExp += x;

    /* Edit our shared preferences unlockedLevels key, setting its
     * value our new mUnlockedLevels value
     */
    mEditor.putInt(EXP_KEY, mPlayerExp);

    /* commit() must be called by the editor in order to save
     * changes made to the shared preference data
     */
    mEditor.commit();
}



/* The setSoundMuted method uses the same idea for storing new data
 * into the shared preferences. First, we overwrite the mSoundEnabled
 * boolean, use the putBoolean method to store the data, and finally
 * commit the data to the shared preferences
 */
public synchronized void setSoundMuted(final boolean pEnableSound) {
    mSoundEnabled = pEnableSound;
    mEditor.putBoolean(SOUND_KEY, mSoundEnabled);
    mEditor.commit();
}
 10-02 15:47:22.212: W/dalvikvm(848): threadid=11: thread exiting with uncaught exception (group=0x40fea2a0)
    10-02 15:47:22.235: E/AndroidRuntime(848): FATAL EXCEPTION: UpdateThread
    10-02 15:47:22.235: E/AndroidRuntime(848): java.lang.NullPointerException
    10-02 15:47:22.235: E/AndroidRuntime(848):  at WorldScene.test.test.UserData.addPlayerGold(UserData.java:143)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at Scene.WorldScene$1.onManagedUpdate(WorldScene.java:115)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.scene.Scene.onManagedUpdate(Scene.java:284)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onUpdateScene(Engine.java:604)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onUpdate(Engine.java:599)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.LimitedFPSEngine.onUpdate(LimitedFPSEngine.java:51)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine.onTickUpdate(Engine.java:561)
    10-02 15:47:22.235: E/AndroidRuntime(848):  at org.andengine.engine.Engine$UpdateThread.run(Engine.java:833)
    10-02 15:47:22.251: W/ActivityManager(470):   Force finishing activity WorldScene.test.test/.WorldActivity
如果从OnManagedUpdate调用,UserData中的unlockNextLevel也会使应用程序崩溃。
为什么我可以打电话检查UserData中的变量,但不更改它们?“

感谢CaptainTeemo的回答

对于任何有类似问题的人, 未初始化UserData,必须在WorldActivity中调用UserData.init:

@Override
protected Scene onCreateScene() {


    this.getEngine().registerUpdateHandler(new FPSLogger());
    // Initializes the Engine
    mWorldEngine = this.getEngine();

    //Start with touch enabled
    TOUCH_ENABLED = true;

    mMainCurtain = new Sprite(0, 0, AssetLoaderUtil.FadeTextureRegion, this.getVertexBufferObjectManager());

    SceneManager.initialize(this);
    SceneManager.mLoadingScene.create();
    SceneManager.mGameIntroScene.create();
    SceneManager.mMainMenuScene.create();

    /////////////////////////
    //ADDED SHAREDPREFS INIT() METHOD \/\/\/
    ////////////////////////

    UserData.getInstance().init(getApplicationContext());

    ...
    }

你能分享UserData类的代码吗,特别是addPlayerGold?Added UserData类你在某处调用你的UserData的init方法吗?NullPointerException在mEditor.putIntPLAYER_GOLD,mPlayerGold行中;如果是,问题是您没有初始化编辑器。