Reputation: 65
I'm a beginner to android development, so pardon me if this is so obvious. I made a basic user management system to practice db connection. My register Activity was crashing because of this segment.
if(Db.getUser(Uid) != null){ //Db is a DatabaseHandler Object
Toast.makeText(getApplicationContext(),"Email is Already Used",Toast.LENGTH_SHORT);
Proceed = false;
}
This is DatabaseHandler.getUser()
User getUser(String Uid) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_UID,
KEY_NAME, KEY_PASS }, KEY_UID + "=?",
new String[] { Uid }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
else
return null; //I explicitly made this statement to return null in case of no match
User user = new User(cursor.getString(0),cursor.getString(1), cursor.getString(2));
// return User
return user;
}
I use django frequently, so i thought that android SQLite also returned something similar to a blank QuerySet. Am I wrong? Does it throw an exception instead? If so what would be the best implementation for the purpose I'm trying to achieve?
Upvotes: 1
Views: 1170
Reputation: 56958
SQLite also returned something similar to a blank QuerySet. Am I wrong?
The query method return a Cursor. It could be described as Blank perhaps (empty where the Cursor's getCount method will return 0 i.e. no extracted data) but not a null.
Does it throw an exception instead?
If you try to read data when the Cursor is positioned at before the first row (the initial position) or after the last row, then you will get an exception. That is you can only read data when the Cursor is positioned at an existing row.
In short your issue is that you are not checking to see if a row exists as the Cursor will not be null.
The query method returns a Cursor which will hold a number of rows that each consist of the columns that have been specified by in the query.
A Cursor returned from the query method will never be null (so checking for null does nothing (your first issue)). However, the Cursor may be empty. As such you need to handle this situation.
To check if a Cursor has returned any rows you can either check the number of rows using the Cursor's getCount method e.g. if (cursor.getCount() > 0) { ... get data from row .. } else { ... handle no rows ... }
Alternately many of the Cursor's move?????
methods return a boolean, true if the move could be made or false if not. e.g. if (moveToFirst()) { ... get data from row .. } else { ... handle no rows ... }
.
You can loop through all returned rows using while(cursor.moveToNext() { ... get data from current row .. };
If so what would be the best implementation for the purpose I'm trying to achieve?
As such your code, where you want to get a row and build and return a single User (there should only be one row that matches the Uid (assuming the column is either explicitly or implicitly defined with the UNIQIUE constraint)) coulde be :-
User getUser(String Uid) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_UID,
KEY_NAME, KEY_PASS }, KEY_UID + "=?",
new String[] { Uid }, null, null, null, null);
if (cursor.moveToFirst()) {
return new User(cursor.getString(csr.getColumnIndex(KEY_UID),cursor.getString(cursor.getColumnIndex(KEY_NAME)),cursor.getString(cursor.getColumnIndex(KEY_PASS));
} else
return null; //I explicitly made this statement to return null in case of no User
}
Note that using the getColumnIndex(the_column_name) reduces the potential for mistakes when determining the column offset e.g.
if you inadvertently used db.query(TABLE_CONTACTS, new String[] { KEY_UID, KEY_PASS, KEY_NAME }, KEY_UID + "=?", new String[] { Uid }, null, null, null, null);
then if using hard coded offsets resultant User would have the password as the name and the name as the pasword. When using the getColumnIndex the position of the columns in the Cursor doesn't matter.
Note the above code is in-principle code, it has not been tested or run and may therefore have errors.
Upvotes: 2