我想使用共享偏好设置作为我的小游戏的高分存储。但我认为我并不完全理解共享偏好背后的概念。
问题是,当游戏结束时,用户应该能够输入他的名字并保存他当前的分数(工作)。我尝试使用共享首选项实现功能。 当我在游戏之后点击我的Highscore活动(保存的高分应该在列表中显示)时(用户还没有离开应用程序)我得到之前保存的最后一个值(如果我在一行并保存它仍然只给我一个高分,还有另一个错误)(已回答)。
如果应用程序已关闭并且我调用了Highscore活动,我会收到异常。 (打开)
我的问题:
共享Prefences是否仅在应用程序运行时存储值并在退出时销毁它们? (回答)
有没有更好的方法来实现我想要的? (回答)
守则:
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();
}
}
答案 0 :(得分:0)
以下是您的问题的答案:
SharedPreferences
是一个持久存储 - 只要应用程序安装在设备上,就会保留任何数据。SharedPreferences
有一些弊端。 prefs是一个键值存储。这意味着密钥应该是唯一的。对于您当前的实现,每次用户提交具有相同名称的新分数时,它将覆盖同一用户的先前分数。有很多方法 - 添加一些独特的键(如时间戳),但是在显示时需要额外的逻辑来管理键等。你也可以使用SharedPreferences
存储某种类型的结构,序列化为JSON并保存数据。但是,当您需要操作它时,您将不得不处理维护,序列化和反序列化此结构的开销。我可以推荐两种选择 - 一种简单的SQLite数据库,可以跟踪用户分数。这样您就可以从其他RDBMS优势中受益 - 排序,查询等。或者,如果您正在开发游戏,您可以考虑将Google Play游戏集成到其中。他们有一个排行榜API,这是让您的游戏更具社交性并适应Android游戏社区的下一步。