3

Question Following tutorial, trying to put some simple string into a database every time I press a button. I believe that the "usernames" are being entered into the database, while debugging it doesn't do anything funny. My problem is when I want to call databaseToString(), I set a Cursor to the first entry. But subsequently it doesn't even enter while(!c.isAfterLast()). What is going on? I want it dbString to pretty much be equal to the database in plaintext, but that's not happening. Thanks

Attempts

  • Checked around SO/Google/API guide/thenewboston source code
  • Tried viewing my SQLite database, but I'm not sure how to do that so I couldn't
  • If you comment out databaseToString then I guess it runs, but it just sits there.
  • It also crashes when I set Text.setText(dbString); but that's completely unrelated

LogCat It doesn't crash, if needed I'll post.

SearchActivity.Java INSERT GETS CALLED WHEN THE BUTTON IS CLICKED

public class SearchActivity extends ActionBarActivity {

    EditText Input;
    TextView Text;
    Database dbHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        Input = (EditText) findViewById(R.id.Input);
        dbHandler = new Database(this, null, null, 1);
        // printDatabase();

    }

    // Add a user to database
    public void insert(View view) {
        Users user = new Users(Input.getText().toString());
        dbHandler.addUser(user);
        printDatabase();
    }


    public void printDatabase() {
        // dbString is returning null
        String dbString = dbHandler.databaseToString();
        //Technically it starts to crash right at this line
        Text.setText(dbString);
        Input.setText("");
    }    
}

Users.java

public class Users {
    private int _id;
    private String _username;

    public Users() {

    }

    public Users(String username){
        this._username = username;
    }

    public String get_username() {
        return _username;
    }

    public void set_username(String username) {
        this._username = username;
    }

    public int get_id() {
        return _id;
    }

    public void set_id(int id) {
        this._id = id;
    }
}

Database.java aka Handler. Look at databaseToString() and the while loop isn't entered whatsoever for some reason.

public class Database extends SQLiteOpenHelper {
    // Version number to upgrade database version
    // each time if you Add, Edit table, you need to change
    // the version number
    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "users.db";
    private static final String TABLE_USERS = "users";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_USERNAME = "username";


    public Database(Context context, String DATABASE_NAME, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // There must be a ',' in between every column definition
        String query = "CREATE TABLE " + TABLE_USERS + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COLUMN_USERNAME + " TEXT " +
                ");";
        db.execSQL(query);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS" + TABLE_USERS);
        onCreate(db);
    }

    //Add a new row to the db
    public void addUser(Users user){
        ContentValues values = new ContentValues();
        values.put(COLUMN_USERNAME, user.get_username());
        SQLiteDatabase db = getWritableDatabase();
        db.insert(TABLE_USERS, null, values);
        db.close();
    }

    public String databaseToString() {
        String dbString = "";
        SQLiteDatabase db = getWritableDatabase();
        String query = "SELECT * FROM " + TABLE_USERS + " WHERE 1";

        // Cursor point to a location in your results
        Cursor c = db.rawQuery(query, null);
        // Move to the first row in your results
        c.moveToFirst();

        while(!c.isAfterLast()) {
            if(c.getString(c.getColumnIndex("username")) != null) {
                dbString += c.getString(c.getColumnIndex("username"));
                dbString += "\n";
            }
        }
        db.close();
        return dbString;
    }
}
Script Kitty
  • 1,737
  • 5
  • 27
  • 47
  • 2
    Get the return value of insert and see what it's returning. If it is returning -1 that means it was not successful. `long retVal = db.insert(TABLE_USERS, null, values);` – Daniel Nugent Jun 10 '15 at 22:41
  • @DanielNugent Thanks for that awesome tip it says I have retVal = 14. At least I know it's working now, thanks – Script Kitty Jun 10 '15 at 22:44
  • 2
    Sure. Next thing to check is the return value of getCount() on the Cursor after the call to rawQuery: `int count = c.getCount()` – Daniel Nugent Jun 10 '15 at 22:49
  • @DanielNugent count = 15, I pressed it a lot earlier. thanks – Script Kitty Jun 10 '15 at 22:53
  • Are you calling `findViewById()` somewhere for `Text`? – Daniel Nugent Jun 10 '15 at 22:57
  • @DanielNugent Yeah, SearchActivity.java line 28;;; EDIT: oh by the way i kept checking c.isAfterLast and now it returns false??? Anyway now it enters the loop – Script Kitty Jun 10 '15 at 23:00
  • 2
    You might have an infinite loop since you're not progressing the Cursor. Add `c.moveToNext();` after `dbString += "\n";` Also, put your `Text = (TextView) findViewById(R.id.Text);` in `onCreate()` to make sure you don't get the NullPointerException. – Daniel Nugent Jun 10 '15 at 23:15
  • @DanielNugent Hey man I was out but thanks so much it's working as perfectly as I expect. If you write up c.moveToNext() I'll accept it. Kudos – Script Kitty Jun 11 '15 at 02:44

2 Answers2

2

Maybe this helps you:

The simplest way is this:

while (cursor.moveToNext()) {
    ...
}

The cursor starts before the first result row, so on the first iteration this moves to the first result if it exists. If the cursor is empty, or the last row has already been processed, then the loop exits neatly.

What's the best way to iterate an Android Cursor?

Community
  • 1
  • 1
user3854270
  • 68
  • 1
  • 8
2

Fixing the NullPointerException:

First, to fix the NullPointerException, initialize Text in onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);

    Input = (EditText) findViewById(R.id.Input);
    Text = (TextView) findViewById(R.id.Text); //added
    dbHandler = new Database(this, null, null, 1);
    // printDatabase();

}

Debugging tips:

In order to make sure that insertion into the database is successful, capture the return value of insert():

long retVal = db.insert(TABLE_USERS, null, values);

Then, to verify that data is present in the Cursor, get the count of the Cursor:

Cursor c = db.rawQuery(query, null);
int count = c.getCount(); //added

Solution:

Finally, there are a few things to add here. First, you need to progress the Cursor in order to not have an infinite loop. Also, you should check the return value of moveToFirst(), and do nothing if it returns false. Lastly, you should close the Cursor when you're done with it, otherwise you'll have a memory leak.

public String databaseToString() {
    String dbString = "";
    SQLiteDatabase db = getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_USERS + " WHERE 1";

    // Cursor point to a location in your results
    Cursor c = db.rawQuery(query, null);
    // Move to the first row in your results
    //check that moveToFirst returns true
    if (c.moveToFirst()){

      while(!c.isAfterLast()) {
        if(c.getString(c.getColumnIndex("username")) != null) {
            dbString += c.getString(c.getColumnIndex("username"));
            dbString += "\n";
        }
        c.moveToNext(); //added
      }

    }
    c.close(); //added
    db.close();
    return dbString;
}
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137