[英]Android app stores high score value as int in sharedpreferences. The app throws an outofbounds exception if a score over 100 is reached
我有一个Android游戏,该游戏使用SharedPreferences在设备上存储游戏的高分。 在设备上的高分超过100分之前,这将非常有效,这将导致应用程序在下次从SharedPreferences获取int时崩溃。 这是与从SharedPreferences中存储和检索分数有关的代码。
public void setHighScore(int score) {
SharedPreferences.Editor settingsEditor = prefs.edit();
settingsEditor.putInt(Constants.KEY_HIGHSCORE, score);
settingsEditor.commit();
}
public int getHighScore() {
return prefs.getInt(Constants.KEY_HIGHSCORE, 0);
}
if (score > activity.getHighScore()) {
activity.setHighScore(score);
}
yourScoreText.setText("Your Score: " + score);
yourScoreText.setColor(Color.GREEN);
yourScoreText.setVisible(true);
highScoreText.setText("High Score: " + activity.getHighScore());
highScoreText.setColor(Color.RED);
highScoreText.setVisible(true);
logcat的
09-19 22:00:13.612: W/dalvikvm(26458): threadid=12: thread exiting with uncaught exception (group=0x417a9898)
09-19 22:00:13.622: E/AndroidRuntime(26458): FATAL EXCEPTION: UpdateThread
09-19 22:00:13.622: E/AndroidRuntime(26458): java.lang.ArrayIndexOutOfBoundsException: length=360; index=360
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.entity.text.vbo.HighPerformanceTextVertexBufferObject.onUpdateVertices(HighPerformanceTextVertexBufferObject.java:124)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.entity.text.Text.onUpdateVertices(Text.java:333)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.entity.shape.Shape.setSize(Shape.java:146)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.entity.text.Text.setText(Text.java:221)
09-19 22:00:13.622: E/AndroidRuntime(26458): at hungryfish.scene.GameScene.reset(GameScene.java:246)
09-19 22:00:13.622: E/AndroidRuntime(26458): at hungryfish.scene.GameScene.onSceneTouchEvent(GameScene.java:308)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.entity.scene.Scene.onSceneTouchEvent(Scene.java:387)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.Engine.onTouchScene(Engine.java:470)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.Engine.onTouchEvent(Engine.java:456)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.input.touch.controller.BaseTouchController$TouchEventRunnablePoolItem.run(BaseTouchController.java:102)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.util.adt.pool.RunnablePoolUpdateHandler.onHandlePoolItem(RunnablePoolUpdateHandler.java:54)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.util.adt.pool.RunnablePoolUpdateHandler.onHandlePoolItem(RunnablePoolUpdateHandler.java:1)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.util.adt.pool.PoolUpdateHandler.onUpdate(PoolUpdateHandler.java:88)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.input.touch.controller.BaseTouchController.onUpdate(BaseTouchController.java:62)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.Engine.onUpdate(Engine.java:604)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.LimitedFPSEngine.onUpdate(LimitedFPSEngine.java:57)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.Engine.onTickUpdate(Engine.java:568)
09-19 22:00:13.622: E/AndroidRuntime(26458): at org.andengine.engine.Engine$UpdateThread.run(Engine.java:858)
我会对此发表评论,但是由于我的得分低于50,所以我不能。.一个简单的解决方案是将值存储在String中。 像这样:
SharedPreferences sp = getSharedPreferences(1);
sp.edit().putString("highScore", String.valueOf(highScore)).apply
而当您从共享首选项中删除它时,只需执行
int score = Integer.valueOf(sp.getString("highScore", "0"));
我个人不是共享首选项的忠实拥护者,而是选择sqlite数据库。 使用数据库时,读/写序列非常快。
您可能要尝试的一件事是使用.apply而不是.commit-.apply在后台运行。
如您所问,我正在提供一些我编写的代码来帮助您使用数据库。 我只是编写并尝试使用它,所以我知道它可以在我的GS3(4.4.4)和OnePlus One(4.4.4)上正常工作或至少可以工作。
我将在单独的文件中创建类,但是由您自己决定。 例如,我只是在默认活动中使用了它们,并在onCreate中运行了一些set / get评分代码。
public class DatabaseHelper extends SQLiteOpenHelper{
//final static stuff because you'll want to access it(the data) in other classes.
public static final String DB_NAME = "scores.db";
public static final String SCORE_TABLE = "scores";
public static final int VERSION = 3;
private Context context;
public DatabaseHelper(Context context){
super(context, DB_NAME, null, VERSION);
this.context = context;
}
public SQLiteDatabase getDatabase(){
return getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
//our code for creating the ScoreTable..
db.execSQL("CREATE TABLE "
+ SCORE_TABLE +
"(" +
"ID INT NOT NULL, " +
"Score INT);");
//now we create one row of data.
db.execSQL("INSERT INTO " + DatabaseHelper.SCORE_TABLE + " (ID, Score) VALUES (1, 0);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//if the version is greater than the previous one, we re-create it.
if(newVersion > oldVersion) {
db.execSQL("DROP TABLE IF EXISTS " + SCORE_TABLE);
onCreate(db);
}
}
}
public class DataSource{
//this is a link between your app and the database. you don't have to use this.
private SQLiteDatabase database;
private Context context;
private DatabaseHelper helper;
public DataSource(Context context){
//initiate our objects.
this.helper = new DatabaseHelper(context);
this.database = helper.getWritableDatabase();
this.context = context;
}
public void setScore(int score){
//we update the Score column where the ID is 1
database.execSQL("UPDATE " + DatabaseHelper.SCORE_TABLE + " SET Score = " + score + " WHERE ID = 1;");
}
public int getScore(){
//we get all of the columns that have a ID of one. There should only be one column.
Cursor score = database.rawQuery("SELECT * FROM " + DatabaseHelper.SCORE_TABLE + " WHERE ID = 1", null);
//this isn't especially needed, but i found that adding checks and balances keeps crashes down.
if(score.getColumnCount() < 1){
return 0;
} else {
//this is important! You have to move the cursor to the first row.
score.moveToFirst();
//now we get the data on row 1 (actually 2 if you look at it from a 1 based number system..)
int mscore = score.getInt(1);
//close the cursor
score.close();
//and finally return the score.
return mscore;
}
}
}
要使用上面的代码,只需创建一个DataSource对象并调用setScore和getScore方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.