android - NullPointerException в onLoadFinished

556
23 декабря 2016, 12:59

Привет. Я новичок в программировании, пытаюсь сделать простенькое приложение для создания напоминаний. Запнулся на работе с лоадером при работе с базой данных. Конкретно, приложение при запуске выдает NullPointerException в методе onLoadFinished ().

Если закомментировать строку swapCursor, то проблема исчезает.Подскажите. пожалуйста, в чем проблема. Это моя главная деятельность со списком напоминаний ReminderListActivity в которой и возникает ошибка. Большое спасибо всем за помощь.

public class ReminderListActivity extends ListActivity implements LoaderManager.LoaderCallbacks <Cursor> {
private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private ReminderDbAdapter mDbHelper;
private ListView remindersList;
SimpleCursorAdapter reminders;
private static final String TAG = "MyActivity";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.reminder_list);
    // открываем подключение к БД
    mDbHelper = new ReminderDbAdapter(this);
    mDbHelper.open();
    fillData();
    registerForContextMenu(getListView());
}
// заполняем список задач
private void fillData() {

    // формируем столбцы сопоставления
    String[] from = new String[]{ReminderDbAdapter.KEY_TITLE,};
    int[] to = new int[]{R.id.text1};
    //создаем адаптер курсора и настраиваем список
    SimpleCursorAdapter reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, null, from, to, 0);
    remindersList = (ListView) findViewById(android.R.id.list);
    remindersList.setAdapter(reminders);
    // создаем лоадер для чтения данных
    getLoaderManager().initLoader(0, null, this);
}
@Override
protected void onListItemClick(ListView l, View v,
                               int position, long id) {
    super.onListItemClick(l, v, position, id);
    super.onListItemClick(l, v, position, id);
    Intent i = new Intent(this,
            ReminderEditActivity.class);
    i.putExtra(ReminderDbAdapter.KEY_TITLE, id);
    startActivityForResult(i, ACTIVITY_EDIT);
}

// ContextMenu
@Override
public void onCreateContextMenu(ContextMenu menu,
                                View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater mi = getMenuInflater();
    mi.inflate(R.menu.list_menu_item_longpress, menu);
}
//Menu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    MenuInflater mi = getMenuInflater();
    mi.inflate(R.menu.list_menu, menu);
    return true;
}
//Choose Menu Item
@Override
public boolean onMenuItemSelected(int featureId,
                                  MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_insert:
            createReminder();
            return true;
    }
    return super.onMenuItemSelected(featureId, item);
}

private void createReminder() {
    Intent i =
            new Intent(this, ReminderEditActivity.class);
            startActivityForResult(i, ACTIVITY_CREATE);
        }
@Override
protected void onActivityResult(int requestCode, int resultCode,
                                Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    getLoaderManager().getLoader(0).forceLoad();
}
//Choose delete item
@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_delete:
            AdapterView.AdapterContextMenuInfo info =
                    (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
            mDbHelper.deleteReminder(info.id);
            return true;
    }
    return super.onContextItemSelected(item);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
    return new MyCursorLoader(this, mDbHelper);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    reminders.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
static class MyCursorLoader extends CursorLoader {
    ReminderDbAdapter mDbHelper;
    public MyCursorLoader(Context context, ReminderDbAdapter mDbHelper) {
        super(context);
        this.mDbHelper = mDbHelper;
    }
    @Override
    public Cursor loadInBackground() {
        Cursor cursor = mDbHelper.fetchAllReminders();
        return cursor;
    }
}

}

Вот деятельность адаптера базы данных ReminderDbAdapter.

public class ReminderDbAdapter {
private static final String DATABASE_NAME = "data";
private static final String DATABASE_TABLE = "reminders";
private static final int DATABASE_VERSION = 1;
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 DatabaseHelper mDbHelper; 
private SQLiteDatabase mDb;

//data base scenario
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 Context mCtx;
public ReminderDbAdapter(Context ctx) {
 this.mCtx = ctx;
 }

//Data base creation
public ReminderDbAdapter open()
         throws android.database.SQLException {
    mDbHelper = new DatabaseHelper(mCtx);
    mDb = mDbHelper.getWritableDatabase();
    return this;
 }

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 {
    Cursor 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.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;
}

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) {
    }
}
//close data base
public void close() {
     mDbHelper.close();
}

Ну и на всякий пожарный, текст логов.

java.lang.NullPointerException
    at com.dummies.android.taskreminder.ReminderListActivity.onLoadFinished(ReminderListActivity.java:143)
    at com.dummies.android.taskreminder.ReminderListActivity.onLoadFinished(ReminderListActivity.java:22)
    at android.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:483)
    at android.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:451)
    at android.content.Loader.deliverResult(Loader.java:143)
    at android.content.CursorLoader.deliverResult(CursorLoader.java:113)
    at android.content.CursorLoader.deliverResult(CursorLoader.java:43)
    at android.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:254)
    at android.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:91)
    at android.os.AsyncTask.finish(AsyncTask.java:631)
    at android.os.AsyncTask.access$600(AsyncTask.java:177)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)
Answer 1

У Вас есть поле класса активити:

SimpleCursorAdapter reminders;

Как и любое другое поле объектного типа, по-умолчанию, reminders инициализируется значением NULL. Далее Вы нигде не инициализируете это после самостоятельно, следовательно, в строке:

reminders.swapCursor(cursor);

получаете NullPointerException.

Однако в методе fillData() Вы создаете некий объект:

SimpleCursorAdapter reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, null, from, to, 0);

который является локальной переменной метода и в этом методе перекрывает одноименное поле класса.

Скорее всего, в этом методе Вы хотели инициализировать поле класса, а не создавать перекрывающую локальную переменную. Если это так, то просто замените:

SimpleCursorAdapter reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, null, from, to, 0);

на:

reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, null, from, to, 0);

В этом случае Вы инициализируете поле класса, и, если эта инициализация происходит ранее вызова метода, в котором фигурирует строка:

reminders.swapCursor(cursor);

, то NullPointerException там Вы уже не получите.

READ ALSO
Нужно достать из таблицы число

Нужно достать из таблицы число

Есть база данных (postgreSQL) в ней имеется таблица с числами типа moneyЗадача достать с этой таблицы это число на языке джава

314
Тень у LinerLayout

Тень у LinerLayout

Подскажите как сделать тень у LinerLayout сверху как на рисунке?

349
Реализация AspectJ Weaving в OSGi (Apache Felix)

Реализация AspectJ Weaving в OSGi (Apache Felix)

Имеем Java web-приложение на платформе OSGiРаботы ведутся с использованием OSGi enRoute и bndtools в среде Eclipse

418
Как реализовать аутентификация между (spring) REST-Cервером и Android приложением

Как реализовать аутентификация между (spring) REST-Cервером и Android приложением

Привет RUSO, есть сервер который предостовляет Rest

386