2016-03-09 2 views
0

У меня есть listview, и когда я нажимаю на элемент списка, пользователь будет перенаправлен на экран редактирования, который будет извлекать данные из базы данных с помощью курсора и заполнять в текстовых полях редактирования. Но я получаю NullPointerException, когда я выбираю элемент списка, и ошибка отображается на cursor.getColumnIndexOrThrow(), хотя БД не пуста.cursor.getColumnIndexOrThrow() throws NullPointerException

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; 
} 

частный 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): \t at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2444) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2472) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1986) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread.access$600(ActivityThread.java:123) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.os.Handler.dispatchMessage(Handler.java:99) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.os.Looper.loop(Looper.java:137) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread.main(ActivityThread.java:4424) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at java.lang.reflect.Method.invokeNative(Native Method) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at java.lang.reflect.Method.invoke(Method.java:511) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t 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): \t at com.dummies.android.taskreminder.ReminderEditActivity.populateFields(ReminderEditActivity.java:181) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at com.dummies.android.taskreminder.ReminderEditActivity.onResume(ReminderEditActivity.java:92) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1154) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.Activity.performResume(Activity.java:4539) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2434) 
 
03-09 15:30:06.643: E/AndroidRuntime(758): \t ... 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'

+0

Можете ли вы опубликовать исключение? – vkislicins

+1

Возможный дубликат [Что такое Исключение Null Указатель и как его исправить?] (Http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do -i-fix-it) – starkshang

+0

@FireSun Ссылка указывает, что такое NullPointerException и как с этим бороться. Но мой вопрос специфичен для курсора Android – san9194

ответ

0

В RemindersDbAdapter.java, использовать эту часть кода

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; 

} 

Вместо

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; 

} 

mCursor is null Поскольку в первую очередь. После выполнения запроса он получит некоторые данные или нет. Затем вам нужно выполнить следующие строки.

0

Вы не ininitate mCursor значения, поэтому после Cursor reminder = mDbHelper.fetchReminder(mRowId);reminder равны нулем и при использовании reminder.getString бросить NPE.

Проблема находится в файле RemindersDbAdapter java, вы не обрабатывали случай, когда mCursor имеет значение null, поэтому он будет всегда равен нулю.

Смежные вопросы