Привет. Я новичок в программировании, пытаюсь сделать простенькое приложение для создания напоминаний.
Запнулся на работе с лоадером при работе с базой данных. Конкретно, приложение при запуске выдает 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)
У Вас есть поле класса активити:
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
там Вы уже не получите.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть база данных (postgreSQL) в ней имеется таблица с числами типа moneyЗадача достать с этой таблицы это число на языке джава
Имеем Java web-приложение на платформе OSGiРаботы ведутся с использованием OSGi enRoute и bndtools в среде Eclipse
Привет RUSO, есть сервер который предостовляет Rest