Question

Help me please, to deal with my mistake.

this LogCat:

01-31 15:20:34.768: W/dalvikvm(2166): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
    01-31 15:20:34.878: E/AndroidRuntime(2166): FATAL EXCEPTION: main
    01-31 15:20:34.878: E/AndroidRuntime(2166): java.lang.IllegalArgumentException: column '_id' does not exist
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:302)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.widget.CursorAdapter.swapCursor(CursorAdapter.java:338)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.widget.SimpleCursorAdapter.swapCursor(SimpleCursorAdapter.java:346)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at ru.zloyel.manager_sutochnoy_arendy_1.KvartityMain.onLoadFinished(KvartityMain.java:178)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at ru.zloyel.manager_sutochnoy_arendy_1.KvartityMain.onLoadFinished(KvartityMain.java:1)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:482)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:450)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.content.Loader.deliverResult(Loader.java:143)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.content.CursorLoader.deliverResult(CursorLoader.java:113)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.content.CursorLoader.deliverResult(CursorLoader.java:43)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:254)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:91)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.os.AsyncTask.finish(AsyncTask.java:631)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.os.Handler.dispatchMessage(Handler.java:99)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.os.Looper.loop(Looper.java:137)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at android.app.ActivityThread.main(ActivityThread.java:4745)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at java.lang.reflect.Method.invokeNative(Native Method)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at java.lang.reflect.Method.invoke(Method.java:511)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    01-31 15:20:34.878: E/AndroidRuntime(2166):     at dalvik.system.NativeStart.main(Native Method)

The error appears after clicking on the button on the main screen appears on the second list and the application crashes.

My class DB.java:

private static final String SQL_CREATE_ENTRIES = "CREATE TABLE "
            + TABLE_NAME + " (" + KvartDB._ID
            + " INTEGER PRIMARY KEY AUTOINCREMENT, " + NAME_COLUMN
            + " text not null, " + CITY_COLUMN + " text not null, "
            + STREET_COLUMN + " text not null, " + HOME_COLUMN + " integer, "
            + KVARTIRA_COLUMN + " integer, " + PRICE_COLUMN + " integer "
            + ");";

KvartiraMain.java

import android.app.ListActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;

import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class KvartityMain extends ListActivity implements
        LoaderCallbacks<Cursor> {

    private KvartDB sqh;
    private static final int ACTIVITY_CREATE = 0;
    private static final int ACTIVITY_EDIT = 1;
    private static final int DELETE_ID = Menu.FIRST + 1;

    private SimpleCursorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.kvartiry_list);
        this.getListView().setDividerHeight(2);
        sqh = new KvartDB(this);

        fillData();
        registerForContextMenu(getListView());
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        // Первоначальный способ. Тоже работает
        // Cursor cursor = dbHelper.getAllTodos();
        // adapter.changeCursor(cursor);

        getLoaderManager().getLoader(0).forceLoad();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    // Реакция на выбор меню
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        switch (item.getItemId()) {
        case R.id.insert:
            createNewTask();
            return true;
        }
        return super.onMenuItemSelected(featureId, item);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.insert:
            createNewTask();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case DELETE_ID:

            // получаем из пункта контекстного меню данные по пункту списка
            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                    .getMenuInfo();

            // извлекаем id записи и удаляем соответствующую запись в БД
            sqh.deleteKvart(info.id);

            // получаем новый курсор с данными
            getLoaderManager().getLoader(0).forceLoad();

            // fillData();

            return true;
        }
        return super.onContextItemSelected(item);
    }

    private void createNewTask() {
        Intent intent = new Intent(this, Kvartiry.class);
        startActivityForResult(intent, ACTIVITY_CREATE);
    }

    private void fillData() {
        // cursor = sqh.getAllKvart();
        // startManagingCursor(cursor);
        //
        String[] from = new String[] { KvartDB.NAME_COLUMN };
        int[] to = new int[] { R.id.label };

        adapter = new SimpleCursorAdapter(this, R.layout.list_row, null, from,
                to, 0);
        setListAdapter(adapter);

        // создаем лоадер для чтения данных
        getLoaderManager().initLoader(0, null, this);
        adapter.notifyDataSetInvalidated();

    }

    // // Теперь создадим адаптер массива и установим его для отображения наших
    // // данных
    // SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
    // R.layout.list_row, cursor, from, to);
    // setListAdapter(notes);
    //
    // }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Intent intent = new Intent(this, Kvartiry.class);
        intent.putExtra(KvartDB._ID, id);
        // активити вернет результат если будет вызвано с помощью этого метода
        startActivityForResult(intent, ACTIVITY_EDIT);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode == RESULT_OK) {
            fillData();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (sqh != null) {
            sqh.close();
        }

    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // TODO Auto-generated method stub
        return new MyCursorLoader(this, sqh);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        // TODO Auto-generated method stub
        adapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // TODO Auto-generated method stub
        adapter.swapCursor(null);
    }

    static class MyCursorLoader extends CursorLoader {
        KvartDB db;

        public MyCursorLoader(Context context, KvartDB db) {
            super(context);
            this.db = db;
        }

        @Override
        public Cursor loadInBackground() {
            Cursor cursor = db.getAllKvart();

            return cursor;
        }
    }
}
Was it helpful?

Solution

You're creating SimpleCursorAdapter with a null Cursor. Obviously a null Cursor doesn't contain an _id column as required by all cursor adapters.

To fix it, pass in a Cursor which has _id in its projection columns.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top