Невозможно вернуть объект Cursor - close () никогда не был явным вызовом error - PullRequest
2 голосов
/ 10 апреля 2011

Эй.Я пытаюсь вернуть объект курсора в свою деятельность, где он будет использоваться в SimpleCursorAdapter, но у меня ошибка close() was never explicity called.Я не могу найти какое-либо решение для этой ошибки, и я собираюсь думать, что это нерешительная ошибка , LOL.

Подумайте со мной.

Ошибкаговорит:

close () никогда не вызывался явно для базы данных '/data/data/com.example.myapp/databases/myDB.db'

И имеетпредупреждение тоже:

Выпуск инструкции в финализаторе.Убедитесь, что вы явно вызываете close () для вашего курсора: SELECT * FROM contact_data ORDER BY duration desc

android.database.sqlite.DatabaseObjectNotClosedException: Приложение не закрывало курсор или объект базы данных, который был открыт здесь

Ошибка в этом методе, то есть в классе DataHandlerDB (имеет дело с базой данных)

public static Cursor selectTopCalls(Context ctx) {

        OpenHelper helper = new OpenHelper(ctx);
        SQLiteDatabase db = helper.getWritableDatabase(); // error is here

        Cursor cursor = db.query(TABLE_NAME_2, null, null, null, null, null,
                "duration desc");

        return cursor;
    }

Этот метод используется в моей деятельности следующим методом:

public void setBasicContent() {

    listview = (ListView) findViewById(R.id.list_view); 

    Log.i(LOG_TAG, "listview " + listview);

    Cursor c = DataHandlerDB.selectTopCalls(this); // here I use the method
    startManagingCursor(c);

    adapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] {               
            DataHandlerDB.CONTACT_NAME_COL,
            DataHandlerDB.CONTACT_NUMBER_COL,
            DataHandlerDB.CONTACT_DURATION_COL,
            DataHandlerDB.CONTACT_DATE_COL }, new int[] {
            R.id.contact_name, R.id.phone_number, R.id.duration, R.id.date });

    Log.i(LOG_TAG, "before setAdapter");

    Toast.makeText(this, "Before setAdapter", Toast.LENGTH_SHORT).show();

    listview.setAdapter(adapter);


}

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

Я пытался закрыть его наМетод selectValues ​​(), но при этом, он говорит, пытается повторно открыть курсор уже закрыт ( что-то в этом роде ).

Я также пытался закрыть курсор и базу данных в onDestroy (), onStop (), но это не сработало.

Вот почему я подумал, что решения для этого не существует.Что я должен делать?

Класс DataHandlerDB.java , имеет метод createDB ():

public static SQLiteDatabase createDB(Context ctx) {
        OpenHelper helper = new OpenHelper(ctx);
        SQLiteDatabase db = helper.getWritableDatabase();
        helper.onOpen(db);
        db.close();
        return db;
    }

и внутренний класс с именем OpenHelper(расширяет SQLiteOpenHelper)

public static class OpenHelper extends SQLiteOpenHelper {

        private final Context mContext;

        OpenHelper(Context context) {

            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            this.mContext = context;

        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            String[] sql = mContext.getString(
                    R.string.MyString_OnCreate).split("\n");

            db.beginTransaction();

            try {
                execMultipleSQL(db, sql);
                db.setTransactionSuccessful();
            } catch (SQLException e) {

                Log.e("Error creating tables and debug data", e.toString());
                throw e;

            } finally {
                db.endTransaction();

            }
        }

        private void execMultipleSQL(SQLiteDatabase db, String[] sql) {

            for (String s : sql) {

                if (s.trim().length() > 0) {

                    db.execSQL(s);
                }
            }

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            /*
             * Log.w("My Database",
             * "Upgrading database, this will drop tables and recreate.");
             * db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db);
             */
        }

        @Override
        public void onOpen(SQLiteDatabase db) {

            super.onOpen(db);
        }

    }

Так что кто-нибудь может помочь мне решить эту проблему ??Спасибо!

1 Ответ

2 голосов
/ 10 апреля 2011

Вместо создания нового OpenHelper в каждом из ваших статических методов, создайте экземпляр вашего DataHandlerDB с текущим контекстом и сделайте так, чтобы класс содержал переменную, заполненную getWritableDatabase. Вы создаете несколько объектов курсора, созданных различными SQLiteOpenHelper объектами, и Android не любит это делать.

Проверьте это для дополнительной информации: http://www.ragtag.info/2011/feb/1/database-pitfalls/

Вот как мне кажется, что ты делаешь вещи ...

public class DataHandlerDB{

    public static SQLiteDatabase createDB(Context ctx) {
        OpenHelper helper = new OpenHelper(ctx);
        SQLiteDatabase db = helper.getWritableDatabase();
        ...
        return db;
    }

    public static Cursor selectTopCalls(Context ctx) {
        OpenHelper helper = new OpenHelper(ctx);
        SQLiteDatabase db = helper.getWritableDatabase(); // error is here
        ...
        return c;
    }

}

Это приводит к нескольким одновременным SQLiteOpenHelper объектам и нескольким SQLiteDatabase объектам и ситуации блокировки, которая у вас есть в данный момент.

Вместо нескольких статических вызовов создайте класс DataHandler, который вы инстанцируете в согласованном контексте, а затем выполните обычные вызовы (вместо статических):

public class DataHandlerDB{
    OpenHelper _helper;
    SQLiteDatabse _db;

    public DataHandlerDB( Context ctx ){
        _helper = new OpenHelper(ctx);
        _db = _helper.getWritableDatabase();
    }

    public SQLiteDatabase createDB() {
        ...
        return db;
    }

    public Cursor selectTopCalls() {
        ...
        return c;
    }

}

public void setBasicContent() {

    ...

    DataHandlerDB handler = new DataHandlerDB( this );
    Cursor c = handler.selectValues();  //.selectTopCalls()?

    ...
}

Когда вы создаете этот объект, он сохраняется 1 OpenHelper и 1 SQLiteDatabase. Это должно облегчить проблемы с SQLite, когда база данных закрыта, прежде чем она сможет получить к ней доступ.

Не забудьте закрыть БД в методе onDestroy вашей деятельности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...