Android: удалить элемент SQLite из списка. Исключение нулевого указателя

Я новичок в Android (и программировании), поэтому надеюсь, что этот вопрос не слишком глуп. Я пытался ответить на свой вопрос с помощью руководств и безуспешно искал через stackoverflow.

Я пытаюсь заполнить список базой данных SQLite: когда я щелкаю элемент в списке, я хочу, чтобы он также удалялся из списка и из базы данных. Из-за отладки я думаю, что проблема связана с моими методами ArrayAdapter, поскольку даже базовые методы здесь, такие как «getCount ()», похоже, не производят выходных данных.

Вот метод для моего класса SQLite DatabaseHandler для получения всех элементов в базе данных и для удаления элемента:

            // Getting All breadcrumbs
    public List<Breadcrumb> getAllBreadcrumbs() {
     List<Breadcrumb> breadcrumbList = new ArrayList<Breadcrumb>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_BREADCRUMBS;

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Breadcrumb breadcrumb = new Breadcrumb();
            breadcrumb.setId(Integer.parseInt(cursor.getString(0)));
            breadcrumb.setBreadcrumbLatitude(cursor.getInt(1));
            breadcrumb.setBreadcrumbLongitude(cursor.getInt(2));
            // Adding location to list
            breadcrumbList.add(breadcrumb);
        } while (cursor.moveToNext());
    }

    // Deleting single breadcrumb
      public void deleteBreadcrumb(Breadcrumb breadcrumb) {
        SQLiteDatabase db = this.getWritableDatabase();
        int id = breadcrumb.getId();
        System.out.println("Comment deleted with id: " + id);
        db.delete(TABLE_BREADCRUMBS, KEY_ID
                + " = " + id, null);
        db.close();
          }

Макет XML для проблемной активности:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".CollectedBreadcrumbsActivity" >

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</ListView>

</LinearLayout>

А вот активность:

public class CollectedBreadcrumbsActivity extends Activity implements OnItemClickListener {

private ListView listview;
private DatabaseHandler db;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_collected_breadcrumbs);

    DatabaseHandler db = new DatabaseHandler(this);
    List<Breadcrumb> breadcrumbs = db.getAllBreadcrumbs();

    listview = (ListView) findViewById(R.id.list);
    ArrayAdapter<Breadcrumb> adapter = new ArrayAdapter<Breadcrumb>(this,
            android.R.layout.simple_list_item_1, breadcrumbs);
        listview.setAdapter(adapter);
    listview.setOnItemClickListener(this);
}

public void onItemClick(AdapterView<?> l, View v, int position, long id) {
    Log.d("HelloListView", "You clicked Item: " + id + " at position:" + position);
    Log.d("HelloListView", "Number of items in adapter:" + listview.getAdapter().getCount());
    @SuppressWarnings("unchecked")
    ArrayAdapter<Breadcrumb> adapter = (ArrayAdapter<Breadcrumb>) listview.getAdapter();
    if (listview.getAdapter().getCount() > 0) {
        Breadcrumb breadcrumb = (Breadcrumb) listview.getAdapter().getItem(position);
        db.deleteBreadcrumb(breadcrumb);
        adapter.remove(breadcrumb);
        }
    adapter.notifyDataSetChanged();
    }
}

Просмотр списка отображается нормально, но когда я нажимаю элемент в списке, приложение вылетает со следующим журналом:

05-07 19:08:40.671: D/HelloListView(29562): You clicked Item: 5 at position:5
05-07 19:08:40.671: W/dalvikvm(29562): threadid=1: thread exiting with uncaught exception (group=0x40e4c438)
05-07 19:08:40.671: E/AndroidRuntime(29562): FATAL EXCEPTION: main
05-07 19:08:40.671: E/AndroidRuntime(29562): java.lang.NullPointerException
05-07 19:08:40.671: E/AndroidRuntime(29562):    at com.detimil.breadcrumbs1.CollectedBreadcrumbsActivity.onItemClick(CollectedBreadcrumbsActivity.java:42)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.widget.AdapterView.performItemClick(AdapterView.java:298)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.widget.AbsListView.performItemClick(AbsListView.java:1268)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.widget.AbsListView$PerformClick.run(AbsListView.java:3059)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.widget.AbsListView$1.run(AbsListView.java:3950)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.os.Handler.handleCallback(Handler.java:615)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.os.Handler.dispatchMessage(Handler.java:92)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.os.Looper.loop(Looper.java:137)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at android.app.ActivityThread.main(ActivityThread.java:4950)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at java.lang.reflect.Method.invokeNative(Native Method)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at java.lang.reflect.Method.invoke(Method.java:511)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
05-07 19:08:40.671: E/AndroidRuntime(29562):    at dalvik.system.NativeStart.main(Native Method)

Опять же, я думаю, что проблема должна быть с моим ArrayAdapter, потому что даже этот журнал Log.d("HelloListView", "Number of items in adapter:" + listview.getAdapter().getCount()); ничего не создает до сбоя приложения.

Если у кого-то есть мысли по этому поводу, буду очень признателен за помощь. Еще раз извините, если это глупый вопрос.

Большое тебе спасибо.


person peopletrees    schedule 08.05.2013    source источник


Ответы (2)


Ваш db это null,

Так как

  DatabaseHandler db = new DatabaseHandler(this);

он создаст локальный экземпляр, но не создаст экземпляр поля db, поэтому сделайте его таким

db = new DatabaseHandler(this);
person Pragnani    schedule 08.05.2013
comment
@peopletrees, просто удалите «DatabaseHandler» из DatabaseHandler db = new DatabaseHandler(this); и принять ответ pragnani - person umesh; 08.05.2013
comment
в строке private DatabaseHandler db; вы создаете только ссылку, а не объект, и объект, который вы создаете, является локальным только для onCreate, поэтому объект будет нулевым вне oncreate - person umesh; 08.05.2013
comment
@peopletrees Pragnani прав. Он просто не очень хорошо это объясняет. У вас есть член закрытого класса db типа DatabaseHelpern в вашем CollectedBreadCrumbsActivity. Внутри onCreate() вы объявляете локальную переменную db также типа DatabaseHelper. Вы можете устранить эту двусмысленность в Java, используя CollectedBreadCrumbsActivity.this.db для ссылки на член уровня класса db. Однако мы предполагаем, что вы не собирались создавать локальный экземпляр db, а затем выбрасывать его, а имели в виду инициализацию члена уровня класса db. Выполнение того, что предлагает Праньяни, исправит это. - person dcow; 08.05.2013
comment
@DavidCowden и Umesh Спасибо за вашу поддержку - person Pragnani; 08.05.2013
comment
@Pragnani, возможно, вы пропустили комментарий peopletrees, потому что он удалил его. Он был не согласен с вами, но тогда я предполагаю, что он понял это и просто удалил комментарии, поскольку они больше не актуальны. Вот почему мы прокомментировали. - person dcow; 08.05.2013
comment
@DavidCowden да, я не смотрел его комментарий. Но еще раз спасибо за вашу поддержку - person Pragnani; 08.05.2013
comment
Большое спасибо! Это сработало. У меня не было телефона Android, чтобы проверить это до сих пор, поэтому я не мог проверить. Сначала я прокомментировал, что я думал, что создал экземпляр класса с помощью private DatabaseHandler db; понял, что так не пойдет, и удалил свой комментарий, как и предполагал Дэвид Кауден. - person peopletrees; 09.05.2013

Ваша БД должна быть инициирована глобально, а не локально.

Я хотел бы добавить, что в целом не рекомендуется использовать ArrayAdapter для загрузки из БД. Вы должны использовать CursorAdapter и CursorLoader для управления базой данных.

Вот хороший учебник по пользовательскому CursorAdapter: ссылка

Еще один для CursorLoaders: ссылка

person oybek.t    schedule 13.02.2014