使用共享首选项作为高分存储

时间:2016-07-29 13:52:41

标签: android sharedpreferences

我想使用共享偏好设置作为我的小游戏的高分存储。但我认为我并不完全理解共享偏好背后的概念。

问题是,当游戏结束时,用户应该能够输入他的名字并保存他当前的分数(工作)。我尝试使用共享首选项实现功能。 当我在游戏之后点击我的Highscore活动(保存的高分应该在列表中显示)时(用户还没有离开应用程序)我得到之前保存的最后一个值(如果我在一行并保存它仍然只给我一个高分,还有另一个错误)(已回答)。

如果应用程序已关闭并且我调用了Highscore活动,我会收到异常。 (打开)

我的问题:

  1. 共享Prefences是否仅在应用程序运行时存储值并在退出时销毁它们? (回答)

  2. 有没有更好的方法来实现我想要的? (回答)

  3. 守则:

    SimpleActivity.java(保存高分的地方):

    builder.setPositiveButton("Save & Exit", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String m_Text = input.getText().toString();
                if(!m_Text.isEmpty() && highScoreInt > 0) {
                    PreferencesManager.initializeInstance(SimpleActivity.this);
                    PreferencesManager prefM = PreferencesManager.getInstance();
                    prefM.setValue(m_Text, highScoreInt);
                    SimpleActivity.this.finish();
                }
            }
        });
    

    HighScoreActivity.java(如果应用程序是新启动的话,我会收到错误,否则它只会给我一个值,即使我保存了更多游戏)

    public class HighScoreActivity extends AppCompatActivity {
    
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_highscore);
        getHighScore();
    
    
    }
    
    public void getHighScore(){
        PreferencesManager.initializeInstance(HighScoreActivity.this);
        PreferencesManager prefM = PreferencesManager.getInstance();
        Map<String, ?> allPref = prefM.getValue();
        if(!allPref.isEmpty()) {
            for (Map.Entry<String, ?> entry : allPref.entrySet()) {
                System.out.println(entry.getKey() + "/" + entry.getValue());
            }
        }
    }
    

    }

    错误(不太了解它,因为我调用了初始化方法?):

        E/AndroidRuntime: FATAL EXCEPTION: main
    
    Process: com.math.mathquiz, PID: 25026
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.math.mathquiz/com.math.mathquiz.HighScoreActivity}: java.lang.IllegalStateException: PreferencesManager is not initialized, call initializeInstance(..) method first.
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
       at android.app.ActivityThread.-wrap11(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5443)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    Caused by: java.lang.IllegalStateException: PreferencesManager is not initialized, call initializeInstance(..) method first.
       at com.math.mathquiz.PreferencesManager.getInstance(PreferencesManager.java:32)
       at com.math.mathquiz.HighScoreActivity.onCreate(HighScoreActivity.java:17)
       at android.app.Activity.performCreate(Activity.java:6259)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 
       at android.app.ActivityThread.-wrap11(ActivityThread.java) 
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 
       at android.os.Handler.dispatchMessage(Handler.java:102) 
       at android.os.Looper.loop(Looper.java:148) 
       at android.app.ActivityThread.main(ActivityThread.java:5443) 
       at java.lang.reflect.Method.invoke(Native Method) 
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
    

    PreferencesManager.java

    public class PreferencesManager {
        private static final String PREF_NAME = "HighScore";
        private static PreferencesManager sInstance;
        private final SharedPreferences mPref;
    
        private PreferencesManager(Context context) {
            mPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        }
    
        public static synchronized void initializeInstance(Context context) {
            if (sInstance == null) {
                sInstance = new PreferencesManager(context);
            }
        }
    
        public static synchronized PreferencesManager getInstance() {
            if (sInstance == null) {
                throw new IllegalStateException(PreferencesManager.class.getSimpleName() +
                        " is not initialized, call initializeInstance(..) method first.");
            }
            return sInstance;
        }
    
        public void setValue(String name, int value) {
            mPref.edit()
                    .putInt(name, value)
                    .commit();
        }
    
        public Map<String, ?> getValue() {
            Map<String, ?> all = mPref.getAll();
            return all;
        }
    
        public void remove(String key) {
            mPref.edit()
                    .remove(key)
                    .commit();
        }
    
        public boolean clear() {
            return mPref.edit()
                    .clear()
                    .commit();
        }
    
    }
    

1 个答案:

答案 0 :(得分:0)

以下是您的问题的答案:

  1. SharedPreferences是一个持久存储 - 只要应用程序安装在设备上,就会保留任何数据。
  2. 在您的案例中使用SharedPreferences有一些弊端。 prefs是一个键值存储。这意味着密钥应该是唯一的。对于您当前的实现,每次用户提交具有相同名称的新分数时,它将覆盖同一用户的先前分数。有很多方法 - 添加一些独特的键(如时间戳),但是在显示时需要额外的逻辑来管理键等。你也可以使用SharedPreferences存储某种类型的结构,序列化为JSON并保存数据。但是,当您需要操作它时,您将不得不处理维护,序列化和反序列化此结构的开销。我可以推荐两种选择 - 一种简单的SQLite数据库,可以跟踪用户分数。这样您就可以从其他RDBMS优势中受益 - 排序,查询等。或者,如果您正在开发游戏,您可以考虑将Google Play游戏集成到其中。他们有一个排行榜API,这是让您的游戏更具社交性并适应Android游戏社区的下一步。