我使用本地数据库将Android应用程序降级。我需要分别获取每个用户的Highscore。我尝试了以下代码以在Textview中获得用户评分
编辑:创建数据库
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "Mydatabase.db";
private static final String TABLE_REGISTER= "register";
public static final String KEY_ID = "id";
public static final String KEY_FIRST_NAME = " first_name";
public static final String KEY_LAST_NAME = "last_name";
public static final String KEY_EMAIL_ID="email_id";
public static final String KEY_MOB_NO = "mobile_number";
public static final String KEY_PASSWORD = "password";
public static final String KEY_SCORE="score";
public static final String CREATE_TABLE="CREATE TABLE " + TABLE_REGISTER + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_FIRST_NAME + " TEXT,"+ KEY_LAST_NAME + " TEXT,"+ KEY_EMAIL_ID + " TEXT,"
+ KEY_MOB_NO + " TEXT," + KEY_PASSWORD + " TEXT ," + KEY_SCORE +
" INTEGER)";
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGISTER);
// Create tables again
onCreate(db); }
void addregister(RegisterData registerdata)
// code to add the new register
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FIRST_NAME,registerdata.getfirstName()); // register first Name
values.put(KEY_lAST_NAME, registerdata. getlastName() ); // register last name
values.put(KEY_EMAIL_ID, registerdata.getEmailId());//register email id
values.put(KEY_MOB_NO, registerdata.getMobNo());//register mobile no
values.put(KEY_PASSWORD, registerdata.getPassword());
values.put(KEY_SCORE,registerdata.getScore());
// Inserting Row
db.insert(TABLE_REGISTER, null, values);
db.close(); // Closing database connection
}
编辑:
下面的代码用于获得单个高分
public int getScoreByUsername(String username){
int highscore = 0;
String[] col=new String[]{"MAX ( " + KEY_SCORE + ") AS Max_Score"};
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor=db.query(TABLE_REGISTER,col,
"email_id=?",new String[]{username},null,null,null,null);
if(cursor.getCount()<1){
cursor.close();
return 0;
}
else if(cursor.getCount()>=1 && cursor.moveToFirst()){
highscore = cursor.getInt(cursor.getColumnIndex(KEY_SCORE));
cursor.close();
}
return highscore;
}
下面的代码用来在textview中显示高分
维护性
highscorelabel.setText(String.valueOf(db.getScoreByUsername(username)));
但是我收到 java.lang.IllegalStateException错误。这里是我的日志
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:511)
at android.database.CursorWindow.getInt(CursorWindow.java:578)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:69)
at com.example.mathu.loginregister.DataBAseHandler.getScoreByUsername(DataBAseHandler.java:201)
at com.example.mathu.loginregister.ResultActivity.onCreate(ResultActivity.java:69)
at android.app.Activity.performCreate(Activity.java:6847)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2785)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1532)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6342)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
答案 0 :(得分:0)
您的问题是,您正在尝试从游标中不存在的列中获取数据。
更改
highscore = cursor.getInt(cursor.getColumnIndex(KEY_SCORE));
收件人
highscore = cursor.getInt(cursor.getColumnIndex("Max_Score"));
推理由注释解释:-
继续, getScoreByEmail 方法也将导致 同样的错误。
原因是游标仅具有以下列名称: 您指定要提取。
Cursor没有按 用作来源的表格(,例如
SELECT *
表示从表格中获取所有列)。 当您有效地说SELECT max(score) AS Max_Score FROM register WHERE email_id=the_value_passed
时,光标会 仅一个列,该列将被命名为 Max_Score (因此 没有得分列,因此没有getColumnIndex的-1)。
P.S。该方法可以简化为:-
public int getScoreByUsername(String username){
int highscore = 0;
String[] col=new String[]{"MAX ( " + KEY_SCORE + ") AS Max_Score"};
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor=db.query(TABLE_REGISTER,col,
"email_id=?",new String[]{username},null,null,null,null);
if(cursor.moveToFirst()) {
highscore = cursor.getInt(cursor.getColumnIndex("Max_Score"));
}
cursor.close();
return highscore;
}
moveToFirst
,如果计数小于1,则moveToFirst
将返回false。下面是一个使用您的代码的工作示例,其中填充了一些空白。结果(尽管每个用户只有1行)表明该代码有效。
该日志包含(如预期的那样):-
Mary's High Score is 70000
Fred's High Score is 50000
在MainActivity中,它具有:-
RegisterData fred = new RegisterData("Fred","Bloggs","fred@bloggs.email","0000 000 000","mypassword",50000);
RegisterData mary = new RegisterData("Mary","Smith","marysmith@emailcom","0000 000 000","mypassword",60000);
mary.addScore(10000);
然后跟着(将2行添加到寄存器表中):-
MyDBHlpr.addregister(fred);
MyDBHlpr.addregister(mary);
然后跟在后面(以根据EmailId检索高分,然后将值输出到日志):-:-
int mary_max_score = MyDBHlpr.getScoreByUsername(mary.getEmailId());
int fred_max_score = MyDBHlpr.getScoreByUsername(fred.getEmailId());
Log.d("HIGHSCORES","Mary's High Score is " + String.valueOf(mary_max_score));
Log.d("HIGHSCORES", "Fred's High Score is " + String.valueOf(fred_max_score));
完整的代码是:-
MainActivity.java
public class MainActivity extends AppCompatActivity {
DBHelper MyDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyDBHlpr = new DBHelper(this);
RegisterData fred = new RegisterData("Fred","Bloggs","fred@bloggs.email","0000 000 000","mypassword",50000);
RegisterData mary = new RegisterData("Mary","Smith","marysmith@emailcom","0000 000 000","mypassword",60000);
mary.addScore(10000);
MyDBHlpr.addregister(fred);
MyDBHlpr.addregister(mary);
int mary_max_score = MyDBHlpr.getScoreByUsername(mary.getEmailId());
int fred_max_score = MyDBHlpr.getScoreByUsername(fred.getEmailId());
Log.d("HIGHSCORES","Mary's High Score is " + String.valueOf(mary_max_score));
Log.d("HIGHSCORES", "Fred's High Score is " + String.valueOf(fred_max_score));
}
}
DBHelper.java (注意包括一些调试代码,请参见下文)
public class DBHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "Mydatabase.db";
private static final String TABLE_REGISTER= "register";
public static final String KEY_ID = "id";
public static final String KEY_FIRST_NAME = " first_name";
public static final String KEY_LAST_NAME = "last_name";
public static final String KEY_EMAIL_ID="email_id";
public static final String KEY_MOB_NO = "mobile_number";
public static final String KEY_PASSWORD = "password";
public static final String KEY_SCORE="score";
public static final String CREATE_TABLE="CREATE TABLE " + TABLE_REGISTER + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_FIRST_NAME + " TEXT,"+ KEY_LAST_NAME + " TEXT,"+ KEY_EMAIL_ID + " TEXT,"
+ KEY_MOB_NO + " TEXT," + KEY_PASSWORD + " TEXT ," + KEY_SCORE +
" INTEGER)";
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.getWritableDatabase();
}
@Override
public synchronized void close() {
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGISTER);
// Create tables again
onCreate(db); }
void addregister(RegisterData registerdata)
// code to add the new register
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FIRST_NAME,registerdata.getfirstName()); // register first Name
values.put(KEY_LAST_NAME, registerdata. getlastName() ); // register last name
values.put(KEY_EMAIL_ID, registerdata.getEmailId());//register email id
values.put(KEY_MOB_NO, registerdata.getMobNo());//register mobile no
values.put(KEY_PASSWORD, registerdata.getPassword());
values.put(KEY_SCORE,registerdata.getScore());
// Inserting Row
db.insert(TABLE_REGISTER, null, values);
db.close(); // Closing database connection
}
public int getScoreByUsername(String username){
int highscore = 0;
String[] col=new String[]{"MAX ( " + KEY_SCORE + ") AS Max_Score"};
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor=db.query(TABLE_REGISTER,col,
"email_id=?",new String[]{username},null,null,null,null);
//<<<<<<<<<< DEBUG CODE
Log.d("CURSOR COUNT","There are " + String.valueOf(cursor.getCount()) + " rows in the Cursor.");
logAllRows();
//<<<<<<<<<< END OF DEBUG CODE
if(cursor.moveToFirst()) {
highscore = cursor.getInt(cursor.getColumnIndex("Max_Score"));
}
cursor.close();
return highscore;
}
//<<<<<<<<<< ADDED METHOD TO SHOW ALL DATA IN THE REGISTER TABLE
public void logAllRows() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(TABLE_REGISTER,null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
RegisterData.java (尽管临时代码 addScore 是根据您的代码创建的)
public class RegisterData {
private String firstName;
private String lastName;
private String EmailId;
private String MobNo;
private String Password;
private int Score;
RegisterData (String firstName,
String lastName,
String EmailId,
String MobNo,
String Password, int Score) {
this.firstName = firstName;
this.lastName = lastName;
this.EmailId = EmailId;
this.MobNo = MobNo;
this.Password = Password;
this.Score = Score;
}
RegisterData (String firstName,
String lastName,
String EmailId,
String MobNo,
String Password) {
new RegisterData(firstName, lastName, EmailId, MobNo, Password, 0);
}
public String getfirstName() {
return firstName;
}
public void setfirstName(String firstName) {
this.firstName = firstName;
}
public String getlastName() {
return lastName;
}
public void setlastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return EmailId;
}
public void setEmailId(String emailId) {
EmailId = emailId;
}
public String getMobNo() {
return MobNo;
}
public void setMobNo(String mobNo) {
MobNo = mobNo;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
public int getScore() {
return Score;
}
public void setScore(int score) {
Score = score;
}
public void addScore(int score) {
Score = Score + score;
}
}
因此,从本质上讲,您所显示的代码很好。检索0的问题必须存在于其他地方。可能是您没有任何行。
但是,已将一些代码添加到DBHelper类中,您可以复制这些代码,这至少应将问题分为将数据添加到表的问题或表中的数据的问题。
dubegging代码分为两部分,都添加到了 getScoreByusername 方法中。
第一部分打印提取的行数,您希望它是1。如果它是1,并且max_score是0,那么问题就必须是score列是0,null或无法转换的值通过 getInt 方法设置为一个数字(因此使用0)。如果为1,则第二部分应该给出问题的指示。
使用上面的示例导致:-
09-16 10:12:18.618 1535-1535/? D/CURSOR COUNT: There are 1 rows in the Cursor.
第二部分从表中提取所有行/列,并使用DatabaseUtils dumpCursor 方法在光标中显示数据。
在上面的示例中(弗雷德一行,玛丽一行)看起来像:-
09-16 10:12:18.618 1535-1535/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@5345b12c
09-16 10:12:18.622 1535-1535/? I/System.out: 0 {
id=1
first_name=Fred
last_name=Bloggs
email_id=fred@bloggs.email
mobile_number=0000 000 000
password=mypassword
score=50000
}
1 {
id=2
first_name=Mary
last_name=Smith
email_id=marysmith@emailcom
mobile_number=0000 000 000
password=mypassword
score=70000
}
<<<<<
您会看到Fred的得分列为50000,Mary的得分列为70000。
如果第一次调试显示选择了1行,那么分数可能不是有效数字,因此不是0。
如果第一次调试显示0,则可能是email_id列与预期不符。