0

I have a listview and when I click on a list item,the user will be re-directed to a edit screen which will fetch data from database using cursor and populate in the edit text fields. But I am getting a NullPointerException when I select the list item and the error is shown at cursor.getColumnIndexOrThrow() even though the DB is not empty.

RemindersDbAdapter.java

public class RemindersDbAdapter {

private static final String DATABASE_NAME = "data";
private static final String DATABASE_TABLE = "reminders";
private static final int DATABASE_VERSION = 4;

public static final String KEY_TITLE = "title";
public static final String KEY_BODY = "body";
public static final String KEY_DATE_TIME = "reminder_date_time";
public static final String KEY_ROWID = "_id";

private static final String TAG = "ReminderDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
Cursor mCursor;
private static final String DATABASE_CREATE = "create table "
           + DATABASE_TABLE + " (" + KEY_ROWID
           + " integer primary key autoincrement, " + KEY_TITLE
            + " text not null, " + KEY_BODY + " text not null, "
           + KEY_DATE_TIME + " text not null);";

private final Context mCtx;

private static class DatabaseHelper extends SQLiteOpenHelper {

    DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(DATABASE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
        onCreate(db);
    }
}


public RemindersDbAdapter(Context ctx) {
    this.mCtx = ctx;
}


public RemindersDbAdapter open() throws SQLException {
    mDbHelper = new DatabaseHelper(mCtx);
    mDb = mDbHelper.getWritableDatabase();
    return this;
}

public void close() {
    mDbHelper.close();
}


public long createReminder(String title, String body,
        String reminderDateTime) {
    ContentValues initialValues = new ContentValues();
    initialValues.put(KEY_TITLE, title);
    initialValues.put(KEY_BODY, body);
    initialValues.put(KEY_DATE_TIME, reminderDateTime);

    return mDb.insert(DATABASE_TABLE, null, initialValues);
}


public boolean deleteReminder(long rowId) {

    return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

public Cursor fetchAllReminders() {

    return mDb.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_TITLE,
            KEY_BODY, KEY_DATE_TIME }, null, null, null, null, null);
}


public Cursor fetchReminder(long rowId) throws SQLException {



    if (mCursor != null && (mCursor.getCount() > 0)) {
        mCursor = mDb.query(true, DATABASE_TABLE, new String[] { KEY_ROWID,
                KEY_TITLE, KEY_BODY, KEY_DATE_TIME }, KEY_ROWID + "="
                + rowId, null, null, null, null, null);
    }
    if (mCursor != null  && mCursor.getCount()>0) 
    { mCursor.moveToFirst(); }

    return mCursor;

}


public boolean updateReminder(long rowId, String title, String body,
        String reminderDateTime) {
    ContentValues args = new ContentValues();
    args.put(KEY_TITLE, title);
    args.put(KEY_BODY, body);
    args.put(KEY_DATE_TIME, reminderDateTime);

    return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
  }

ReminderEditActivity

public class ReminderEditActivity extends Activity {

// 
// Dialog Constants
//
private static final int DATE_PICKER_DIALOG = 0;
private static final int TIME_PICKER_DIALOG = 1;

// 
// Date Format 
//
   private static final String DATE_FORMAT = "yyyy-MM-dd"; 
   private static final String TIME_FORMAT = "kk:mm";
  public static final String DATE_TIME_FORMAT = "yyyy-MM-dd kk:mm:ss";

private EditText mTitleText;
private EditText mBodyText;
private Button mDateButton;
private Button mTimeButton;
private Button mConfirmButton;
private Long mRowId;
private RemindersDbAdapter mDbHelper;
private Calendar mCalendar;  

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mDbHelper = new RemindersDbAdapter(this);

    setContentView(R.layout.reminder_edit);

    mCalendar = Calendar.getInstance(); 
    mTitleText = (EditText) findViewById(R.id.title);
    mBodyText = (EditText) findViewById(R.id.body);
    mDateButton = (Button) findViewById(R.id.reminder_date);
    mTimeButton = (Button) findViewById(R.id.reminder_time);

    mConfirmButton = (Button) findViewById(R.id.confirm);

    mRowId = savedInstanceState != null ? savedInstanceState.getLong(RemindersDbAdapter.KEY_ROWID) 
                                        : null;

    registerButtonListenersAndSetDefaultText();
}

private void setRowIdFromIntent() {
    if (mRowId == null) {
        Bundle extras = getIntent().getExtras();            
        mRowId = extras != null ? extras.getLong(RemindersDbAdapter.KEY_ROWID) 
                                : null;

    }
}

@Override
protected void onPause() {
    super.onPause();
    mDbHelper.close(); 
}

@Override
protected void onResume() {
    super.onResume();
    mDbHelper.open(); 
    setRowIdFromIntent();
    populateFields();
}

@Override
protected Dialog onCreateDialog(int id) {
    switch(id) {
        case DATE_PICKER_DIALOG: 
            return showDatePicker();
        case TIME_PICKER_DIALOG: 
            return showTimePicker(); 
    }
    return super.onCreateDialog(id);
}

private DatePickerDialog showDatePicker() {


    DatePickerDialog datePicker = new DatePickerDialog(ReminderEditActivity.this, new DatePickerDialog.OnDateSetListener() {

        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
            mCalendar.set(Calendar.YEAR, year);
            mCalendar.set(Calendar.MONTH, monthOfYear);
            mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            updateDateButtonText(); 
        }
    }, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH)); 
    return datePicker; 
}

private TimePickerDialog showTimePicker() {

    TimePickerDialog timePicker = new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {

        @Override
        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
            mCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
            mCalendar.set(Calendar.MINUTE, minute); 
            updateTimeButtonText(); 
        }
    }, mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE), true); 

    return timePicker; 
}

private void registerButtonListenersAndSetDefaultText() {

    mDateButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            showDialog(DATE_PICKER_DIALOG);  
        }
    }); 


    mTimeButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            showDialog(TIME_PICKER_DIALOG); 
        }
    }); 

    mConfirmButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            saveState(); 
            setResult(RESULT_OK);
            Toast.makeText(ReminderEditActivity.this, getString(R.string.task_saved_message), Toast.LENGTH_SHORT).show();
            finish(); 
        }

    });

      updateDateButtonText(); 
      updateTimeButtonText();
}

private void populateFields()  {



    // Only populate the text boxes and change the calendar date
    // if the row is not null from the database. 
    if (mRowId != null) {
        Cursor reminder = mDbHelper.fetchReminder(mRowId);
        System.out.println("RowID "+mRowId);
        startManagingCursor(reminder);
        mTitleText.setText(reminder.getString(
                reminder.getColumnIndexOrThrow(RemindersDbAdapter.KEY_TITLE)));
        mBodyText.setText(reminder.getString(
                reminder.getColumnIndexOrThrow(RemindersDbAdapter.KEY_BODY)));


        // Get the date from the database and format it for our use. 
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
        Date date = null;
        try {
            String dateString = reminder.getString(reminder.getColumnIndexOrThrow(RemindersDbAdapter.KEY_DATE_TIME)); 
            date = dateTimeFormat.parse(dateString);
            mCalendar.setTime(date); 
        } catch (ParseException e) {
            Log.e("ReminderEditActivity", e.getMessage(), e); 
        } 
    } else {
        // This is a new task - add defaults from preferences if set. 
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 
        String defaultTitleKey = getString(R.string.pref_task_title_key); 
        String defaultTimeKey = getString(R.string.pref_default_time_from_now_key); 

        String defaultTitle = prefs.getString(defaultTitleKey, null);
        String defaultTime = prefs.getString(defaultTimeKey, null); 

        if(defaultTitle != null)
            mTitleText.setText(defaultTitle); 

        if(defaultTime != null)
            mCalendar.add(Calendar.MINUTE, Integer.parseInt(defaultTime));

    }

    updateDateButtonText(); 
    updateTimeButtonText(); 

}

private void updateTimeButtonText() {
    // Set the time button text based upon the value from the database
    SimpleDateFormat timeFormat = new SimpleDateFormat(TIME_FORMAT); 
    String timeForButton = timeFormat.format(mCalendar.getTime()); 
    mTimeButton.setText(timeForButton);
}

private void updateDateButtonText() {
    // Set the date button text based upon the value from the database 
    SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); 
    String dateForButton = dateFormat.format(mCalendar.getTime()); 
    mDateButton.setText(dateForButton);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putLong(RemindersDbAdapter.KEY_ROWID, mRowId);
}



private void saveState() {
    String title = mTitleText.getText().toString();
    String body = mBodyText.getText().toString();

    SimpleDateFormat dateTimeFormat = new SimpleDateFormat(DATE_TIME_FORMAT); 
    String reminderDateTime = dateTimeFormat.format(mCalendar.getTime());

    if (mRowId == null) {

        long id = mDbHelper.createReminder(title, body, reminderDateTime);
        if (id > 0) {
            mRowId = id;
        }
    } else {
        mDbHelper.updateReminder(mRowId, title, body, reminderDateTime);
    }
   /* Intent i=new Intent(ReminderEditActivity.this,ReminderService.class);
    i.putExtra("title", title);
    i.putExtra("description", body);
    i.putExtra("date", reminderDateTime);
    startService(i);*/
    new ReminderManager(this).setReminder(mRowId, mCalendar); 


}

}

Logcat

03-09 15:29:56.554: I/System.out(758): Reminders 1
03-09 15:29:56.733: D/gralloc_goldfish(758): Emulator without GPU emulation detected.
03-09 15:29:56.774: I/dalvikvm(758): threadid=3: reacting to signal 3
03-09 15:29:56.804: I/dalvikvm(758): Wrote stack traces to '/data/anr/traces.txt'
03-09 15:30:06.613: I/System.out(758): RowID 1
03-09 15:30:06.613: D/AndroidRuntime(758): Shutting down VM
03-09 15:30:06.623: W/dalvikvm(758): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
03-09 15:30:06.643: E/AndroidRuntime(758): FATAL EXCEPTION: main
03-09 15:30:06.643: E/AndroidRuntime(758): java.lang.RuntimeException: Unable to resume activity {com.dummies.android.taskreminder/com.dummies.android.taskreminder.ReminderEditActivity}: java.lang.NullPointerException
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2444)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2472)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1986)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.access$600(ActivityThread.java:123)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.os.Handler.dispatchMessage(Handler.java:99)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.os.Looper.loop(Looper.java:137)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.main(ActivityThread.java:4424)
03-09 15:30:06.643: E/AndroidRuntime(758):  at java.lang.reflect.Method.invokeNative(Native Method)
03-09 15:30:06.643: E/AndroidRuntime(758):  at java.lang.reflect.Method.invoke(Method.java:511)
03-09 15:30:06.643: E/AndroidRuntime(758):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-09 15:30:06.643: E/AndroidRuntime(758):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-09 15:30:06.643: E/AndroidRuntime(758):  at dalvik.system.NativeStart.main(Native Method)
03-09 15:30:06.643: E/AndroidRuntime(758): Caused by: java.lang.NullPointerException
03-09 15:30:06.643: E/AndroidRuntime(758):  at com.dummies.android.taskreminder.ReminderEditActivity.populateFields(ReminderEditActivity.java:181)
03-09 15:30:06.643: E/AndroidRuntime(758):  at com.dummies.android.taskreminder.ReminderEditActivity.onResume(ReminderEditActivity.java:92)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1154)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.Activity.performResume(Activity.java:4539)
03-09 15:30:06.643: E/AndroidRuntime(758):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2434)
03-09 15:30:06.643: E/AndroidRuntime(758):  ... 12 more
03-09 15:30:06.893: I/dalvikvm(758): threadid=3: reacting to signal 3
03-09 15:30:06.993: I/dalvikvm(758): Wrote stack traces to '/data/anr/traces.txt'
03-09 15:30:07.013: D/dalvikvm(758): GC_CONCURRENT freed 146K, 3% free 12859K/13127K, paused 7ms+62ms
03-09 15:30:07.243: I/dalvikvm(758): threadid=3: reacting to signal 3
03-09 15:30:07.273: I/dalvikvm(758): Wrote stack traces to '/data/anr/traces.txt'
san9194
  • 25
  • 6
  • Can you post the exception? – vkislicins Mar 09 '16 at 11:25
  • 1
    Possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – starkshang Mar 09 '16 at 11:31
  • @FireSun The link specifies what is NullPointerException and how to deal with it. But my question is specific to android cursor – san9194 Mar 09 '16 at 11:40
  • what's your 180th line code?It seems like your code doesn't adjust to your exception. – starkshang Mar 09 '16 at 11:45
  • @FireSun mTitleText.setText(reminder.getString( reminder.getColumnIndexOrThrow(RemindersDbAdapter.KEY_TITLE))); I removed the comments so that it wont look like a big chunk of code – san9194 Mar 09 '16 at 11:47
  • @san9194 Would you please add the full ReminderEditActivity.java class? – SkyWalker Mar 09 '16 at 12:01

2 Answers2

1

In RemindersDbAdapter.java, use this portion code

public Cursor fetchReminder(long rowId) throws SQLException {
        mCursor = mDb.query(true, DATABASE_TABLE, new String[] { KEY_ROWID,
                KEY_TITLE, KEY_BODY, KEY_DATE_TIME }, KEY_ROWID + "="
                + rowId, null, null, null, null, null);
    if (mCursor != null  && mCursor.getCount()>0) 
    { mCursor.moveToFirst(); }

    return mCursor;

}

Instead of

public Cursor fetchReminder(long rowId) throws SQLException {
    if (mCursor != null && (mCursor.getCount() > 0)) { //this line have to remove
        mCursor = mDb.query(true, DATABASE_TABLE, new String[] { KEY_ROWID,
                KEY_TITLE, KEY_BODY, KEY_DATE_TIME }, KEY_ROWID + "="
                + rowId, null, null, null, null, null);
    } // this line have to remove for early removal
    if (mCursor != null  && mCursor.getCount()>0) 
    { mCursor.moveToFirst(); }

    return mCursor;

}

Because primarily mCursor is null. After executing query, he will get some data or not. Then you have to execute next lines.

SkyWalker
  • 24,796
  • 7
  • 62
  • 118
0

You didn't ininitate mCursor value,so after Cursor reminder = mDbHelper.fetchReminder(mRowId); reminder is null and when you use reminder.getString throw NPE.

The problem is located in RemindersDbAdapter java file,you didn't handle the case where mCursor is null,so it will be always null.

starkshang
  • 7,050
  • 6
  • 34
  • 50