Время жизни курсора базы данных Android - PullRequest
0 голосов
/ 03 сентября 2011

Я пытался понять и решить эту проблему в течение последних трех дней. У меня есть несколько ListActivities, где каждый запрашивает одну и ту же базу данных. В каждом действии я закрываю и снова открываю соединение с БД в onPause () и onResume () соответственно. Я заполняю списочные адаптеры курсорами, которые также закрываю и открываю снова:

@Override
public void onPause(){
    super.onPause();

    if(currentCursor != null){
        currentCursor.close();
        currentCursor = null;
    }

    if(mDbHelper != null){
        mDbHelper.close();
        mDbHelper = null;
    }
}

@Override
public void onResume(){
    super.onResume();
    if(mDbHelper == null){
        mDbHelper = new DbHelper(this);
        mDbHelper.open();
    }

    if(currentCursor == null){
        new LoadNewListTask().execute();
    }
}


private class LoadNewListTask extends AsyncTask<String, Void, String> {
    ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(context);
        dialog.setMessage("Loading...");
        dialog.show();
    }
    @Override
    protected String doInBackground(String... arg0) {
        try{
            currentCursor = mDbHelper.fetchNewRows();
        }catch(Exception e){}
        return null;
    }
    @Override
    protected void onPostExecute(String arg){
        if(dialog != null && dialog.isShowing()){
            dialog.dismiss();
        }
        if(currentCursor != null && currentCursor.getCount()>0){
            String[] from = new String[]{DbHelper.KEY_ID, sortingColumn};
            int[] to = new int[]{R.id.ai_about_author_btn, R.id.ai_author_name};

            MyAlphabetizedAdapter notes = new MyAlphabetizedAdapter(this, R.layout.author_index_item, currentCursor, from, to, sortingColumn);
            setListAdapter(notes);
        }
    }
}

На первый взгляд это работает хорошо, однако, когда я быстро перемещаюсь между действиями, я иногда получаю раздражающие Исключения Курсора, одно из которых говорит следующее:

05-01 14:45:05.849: ERROR/AndroidRuntime(1145):
java.lang.IllegalStateException: attempt to acquire a reference on a
close SQLiteClosable
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:31)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:56)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1118)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1092)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
apt.tutorial.Restaurant.getAll(Restaurant.java:14)

и еще один говорит это (это происходит много на устройствах 2.1):

09-03 11:30:19.713: INFO/dalvikvm(2541): Uncaught exception thrown by finalizer (will be discarded):
09-03 11:30:19.713: INFO/dalvikvm(2541): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@45b99828 on null that has not been deactivated or closed
09-03 11:30:19.713: INFO/dalvikvm(2541):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
09-03 11:30:19.713: INFO/dalvikvm(2541):     at dalvik.system.NativeStart.run(Native Method)

Более того, одна из моих функций ListActivities реализует AlphabetIndexer, где я должен передать курсор. Очень странная вещь происходит после того, как я покидаю занятие и возвращаюсь, используя кнопку «Назад». Список заполняется (как и ожидалось), однако, когда я пытаюсь использовать быструю прокрутку, я получаю нулевое исключение для курсора, даже при том, что я создал его заново и заново заполнил список onResume ().

Для меня похоже, что ОС не может правильно обрабатывать несколько курсоров или, может быть, я что-то здесь упускаю?

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 03 сентября 2011

В общем, у меня были проблемы с действиями, в которых пытались поддерживать работу нескольких курсоров.Особенно, когда пытаюсь использовать управляемый курсор, которого я сейчас стараюсь избегать, если это возможно (плюс они устарели).Теперь я пытаюсь открыть курсор, заполнить массив объектов данными, которые мне нужны, закрыть курсор и затем использовать ArrayAdapter для заполнения ListView.Если вам НУЖНО поддерживать курсор активным, и вам это нужно только в том случае, если другие действия в вашем стеке изменяют данные, используйте менеджер курсора или, что еще лучше, более новый CursorLoader.При этом не закрывайте курсор, так как ваша деятельность будет управлять жизненным циклом курсора для вас.

2 голосов
/ 03 сентября 2011

Поскольку вы запускаете асинхронную задачу и быстро покидаете действие, это означает, что при возврате задачи у вас будет выход из этого действия, поэтому был вызван onPause() и курсор не закрыт.Вы можете попробовать отменить асинхронную задачу в onPause().

...