IllegalStateException: база данных уже закрыта (с использованием ViewPager)

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

Мой код:

Cursor, возвращаемый из fetchAllAssignments(), используется для заполнения ListView с помощью пользовательского CursorAdapter. ListView является содержимым ListFragment, и на каждой странице ViewPager отображается несколько экземпляров этого ListFragment (один для отображения заданий из всех курсов, а затем страница для каждого из отдельных курсов).

public Cursor fetchIncompleteAssignments(Short course) {
    DbAdapter adapter = new DbAdapter(context, null, Values.ASSIGNMENT_TABLE);
    adapter.open();

    Cursor r;
    if (course == null) // Fetching from all courses
        r = adapter.fetchAllWhere(Values.ASSIGNMENT_LIST_FETCH, Values.ASSIGNMENT_KEY_STATUS + "=" + 0, Values.ASSIGNMENT_KEY_DUE_DATE);
    else
        r = adapter.fetchAllWhere(Values.ASSIGNMENT_LIST_FETCH, Values.ASSIGNMENT_KEY_COURSE + "=" + course
            + " AND " + Values.ASSIGNMENT_KEY_STATUS + "=" + 0, Values.ASSIGNMENT_KEY_DUE_DATE);
    adapter.close();
    return r;
}

// Part of DbAdapter:
public DbAdapter open() throws SQLException {
    dbHelper = new DatabaseHelper(context);
    db = dbHelper.getWritableDatabase();
    return this;
}

public void close() {
    if (db != null) {
        try {
            db.close();
            dbHelper.close();
        } catch (NullPointerException e) {
            Log.e("Close", "Error: " + e + " " + e.getMessage());
        }
    } else
        Log.e("Close", "Error! db \"" + DATABASE_TABLE + "\" is null.");
}

Любые идеи относительно того, что не так? Насколько я знаю, я правильно закрываю свою базу данных. Дайте мне знать, если вам нужно больше кода. Заранее спасибо!

EDIT: данные извлекаются из базы данных и также заполняют ListView. Я могу пролистать различные страницы, но, кажется, происходит сбой всякий раз, когда фрагмент останавливается. Он часто падает, когда я запускаю другое действие, но не всегда. Он также иногда вылетает, когда я пролистываю страницы, хотя и очень редко. Вот мой метод onPause() для моего фрагмента (у меня нет onStop() или onDestroy()):

В моем onResume() я просто перезагружаю список из базы и получаю новую копию контекста через getActivity(). Возможно что-то очищается (для памяти) и я не перезагружаю? Я не получаю никаких исключений NullPointerException, поэтому мне это кажется маловероятным...

public void onPause() {
    super.onPause();
    if (!assignmentsCursor.isClosed()) {
        assignmentsCursor.close();
        assignmentsCursor = null;
    }
}

это исключение на самом деле возникает, потому что вы дважды закрываете свою базу данных, а не потому, что вы ее не закрыли.


person mightimaus    schedule 03.10.2012    source источник


Ответы (2)


в вашем методе close() замените следующую строку в вашем коде:

so..

с участием:

if (db != null) {

Сделайте close() одноэлементным, как описано в этом пост.

if (db != null && db.isOpen()) {
person kdehairy    schedule 03.10.2012
comment
спасибо @EverythingTech96, если это решило вашу проблему, дайте мне знать. - person mightimaus; 04.10.2012
comment
Думаю, это помогло. Он по-прежнему иногда падает, но я думаю, что гораздо меньше. В любом случае хороший совет, спасибо! :) Любые другие идеи? - person kdehairy; 04.10.2012

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

person Alex Lockwood    schedule 03.10.2012
comment
Если вы сделали свой _1_ синглтоном, вам не нужно его закрывать. - person mightimaus; 03.10.2012
comment
Нужно ли закрывать DbHelper (_2_)? - person Alex Lockwood; 03.10.2012
comment
И мне когда-либо понадобится закрыть мой DbHelper? (например, когда я останавливаю активность) - person mightimaus; 04.10.2012
comment
Можно оставить его открытым ... он не будет потреблять значительный объем ресурсов памяти, пока он открыт, и он будет закрыт, когда процесс приложения будет уничтожен ОС. Это всегда был мой подход ... и, на мой взгляд, это лучший способ легко использовать вашу базу данных в нескольких действиях. - person mightimaus; 04.10.2012
comment
@EverythingTech96 EverythingTech96, кстати, это тот же подход, который использует ContentProvider ... он создает _1_ в _2_, а затем оставляет его открытым для всего жизненного цикла приложения. Наконец, _3_ закрывается, когда приложение завершает работу, и ядро ​​очищает процесс. - person Alex Lockwood; 04.10.2012
comment
НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: основной java.lang.IllegalStateException: база данных /data/data/com.acedit.assignamo/databases/data.db (conn# 0) уже закрыта на android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2082 ) в android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:413) в android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:400) в android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java: 79) в android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164) в android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:147) в android.database.AbstractCursor.moveToPosition(AbstractCursor.java:178) ) в android.support.v4.widget.CursorAdapter.getItemId(CursorAdapter.java:225) в android.widget.AbsListView.onSaveInstanceState(AbsListView.java:1569) в android.view.View.dispatchSaveInstanceState(View.java:9868) в android.view.ViewGroup.dispatchFreezeSelfOnly(ViewGroup. java:2310) в android.widget.AdapterView.dispatchSaveInstanceState(AdapterView.java:770) в android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2296) в android.view.View.saveHierarchyState(View.java:9851) в android.support.v4.app.FragmentManagerImpl.saveFragmentViewState(FragmentManager.java:1561) в android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:962) в android.support.v4.app.FragmentManagerImpl.detachFragment( FragmentManager.java:1233) в android.support.v4.app.BackStackRecord.run(BackStackRecord.java:620) в android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1431) в android.support.v4 .app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431) в android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) в android.support.v4.view.ViewPager.populate(ViewPager.java:895) ) на android.support.v4.v iew.ViewPager.populate(ViewPager.java:772) в android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1539) в android.support.v4.view.ViewPager.computeScroll(ViewPager.java:1422) в android.view.View.getDisplayList(View.java:10406) в android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597) в android.view.View.getDisplayList(View.java:10380) в android.view. ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597) на android.view. View.getDisplayList(View.java:10380) в android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597) в android.view.View.getDisplayList(View.java:10380) в android.view.ViewGroup.dispatchGetDisplayList(ViewGroup .java:2597) в android.view.View.getDisplayList(View.java:10380) в android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:875) в android.view.ViewRootImpl.draw(ViewRootImpl.java: 1910) в android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634) в android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442) в android.os.Handler.dispatchMessage(Handler.java:99) в android. os.Looper.loop(Looper.java:137) в android.app.ActivityThread.main(ActivityThread.java:4575) в java.lang.reflect.Method.invokeNative(собственный метод) в java.lang.reflect.Method. вызывать(Method.java:511) в com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) в co m.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) в dalvik.system.NativeStart.main(собственный метод) - person Alex Lockwood; 04.10.2012