java.lang.IllegalStateException : attempt to re-open an already-closed object: SQLiteQuery 错误

标签 java android

所以我有这个奇怪的错误。我正在为我的建议 searchView 和数据库使用简单的光标适配器。我不需要内容提供者,所以我没有使用它。问题是我在代码中的任何地方都没有关闭数据库或游标的命令,但我仍然收到此错误。 错误:

    java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT _id as _id, title as suggest_text_1, subTitle as suggest_text_2, imgUrl as suggest_icon_1, searchID as suggest_intent_data_id FROM suggestions WHERE (title like ? ) ORDER BY title asc  LIMIT 10
        at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
        at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58)
        at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:152)
        at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:124)
        at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:214)
        at android.support.v4.widget.CursorAdapter.getItemId(CursorAdapter.java:225)
        at android.widget.AdapterView.rememberSyncState(AdapterView.java:1199)
        at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:815)
        at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6117)
        at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
        at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
        at android.support.v4.widget.CursorAdapter.swapCursor(CursorAdapter.java:347)
        at android.support.v4.widget.SimpleCursorAdapter.swapCursor(SimpleCursorAdapter.java:326)
        at android.support.v4.widget.CursorAdapter.changeCursor(CursorAdapter.java:315)
        at android.support.v4.widget.CursorFilter.publishResults(CursorFilter.java:68)
        at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

我的建议方法:

  public synchronized Cursor getSuggestions(String[] selectionArgs) {
    String selection = FIELD_title + " like ? ";

    if (selectionArgs != null) {
        if (!selectionArgs[0].isEmpty()) {
            selectionArgs[0].replaceAll("'", "");
            selectionArgs[0] = "%" + selectionArgs[0] + "%";
        } else {
            selection = null;
            selectionArgs = null;
        }
    }

    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setProjectionMap(mAliasMap);
    queryBuilder.setTables(TABLE2_NAME);
    SQLiteDatabase db = mSearchDBOpenHelper.getReadableDatabase();
    Cursor c = null;
    if (db.isOpen()) {
        c = queryBuilder.query(db,
                new String[]{"_ID",
                        SearchManager.SUGGEST_COLUMN_TEXT_1,
                        SearchManager.SUGGEST_COLUMN_TEXT_2,
                        SearchManager.SUGGEST_COLUMN_ICON_1,
                        SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID},
                selection,
                selectionArgs,
                null,
                null,
                FIELD_title + " asc ", "10"
        );
    }
    return c;
}

现在我想指出我的数据库只实例化了一次,我没有泄漏它而且我只有一个 Activity 。我注意到的是,当存在竞争条件时,更可能发生此错误。我的 onQueryTextChange 监听器:

public boolean onQueryTextChange(String newText) {
            query = newText;
            query = query.replaceAll("[\\s%\"^#<>{}\\\\|`]", "%20");

            if (query.length() > 1) {
            // same problem here
               fireOtherMethod();
            } else {
                    String[] selArgs = {query};
                    searchDB.cleanAutoCompleteRecords();
                    Log.e("c.isClosed()", String.valueOf(searchDB.getSuggestions(selArgs).isClosed()));
                     searchAdapter.changeCursor(searchDB.getSuggestions(selArgs));
            }

            return true;
        }

日志报告游标始终打开,我的数据库也是。当我尝试更改光标时发生错误:

searchAdapter.changeCursor(searchDB.getSuggestions(selArgs));

所以如果我只是开火:

searchDB.getSuggestions(selArgs)

没有问题,没有崩溃。

我无法捕捉到这个错误。我不知道我做错了什么。任何帮助将不胜感激!

更新: 我试过这样做:

Cursor c = searchDB.getSuggestions(selArgs); 
Cursor oldC = searchAdapter.getCursor(); 
if (oldC != null && !oldC.isClosed()) 
  oldC.close(); 
if (!c.isClosed()) 
  searchAdapter.changeCursor(c); 
else searchAdapter.changeCursor(null);

但结果是一样的。

最佳答案

我设法找到了解决方案。似乎问题出在 changeCursor 方法中:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.0_r1/android/widget/CursorAdapter.java#CursorAdapter.changeCursor%28android.database.Cursor%29

当我用退格键从 searchView 中清除文本时,我认为发生了什么,事件被调用了很多次,并且 changeCursor 方法也被调用了。这将关闭旧游标,也许此时旧游标有可能正在尝试从数据库进行查询。所以我覆盖了 changeCursor 方法:

        searchAdapter = new SimpleCursorAdapter(getApplicationContext(), R.layout.suggestionrow, null, from, to, 0) {
        @Override
        public void changeCursor(Cursor cursor) {
            super.swapCursor(cursor);
        }
    };

现在一切都很好。

关于java.lang.IllegalStateException : attempt to re-open an already-closed object: SQLiteQuery 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30681308/

相关文章:

android - 如何从Android中的FCM数据消息中获取值(value)?

android - 如何在 android webview 中使用代码发送 POST 数据

java - 卡夫卡 : No message seen on console consumer after message sent by Java Producer

java - 将 JUnit 5 参数注入(inject)@BeforeEach

android - 无法通过启动完成接收器中的 onReceive() 进行调试

javascript - 如何从数据库下载图像?

java - 如何在android中使用cardview

java - 隐藏 JComBox 框箭头

java - 如何使用 J2V8 在 Android 中使用 NodeJS

java - Spring MVC 的 DelegatingFilterProxy 有什么意义?