博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQLite cursor.moveToNext()
阅读量:5134 次
发布时间:2019-06-13

本文共 3832 字,大约阅读时间需要 12 分钟。

cursor.moveToNext()会出异常,如下

E/AndroidRuntime( 2249): FATAL EXCEPTION: Thread-49

E/AndroidRuntime( 2249): java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
E/AndroidRuntime( 2249): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
E/AndroidRuntime( 2249): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
E/AndroidRuntime( 2249): at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245)

 

 

解决办法,调用cursor.getCount().

原因大概如下:

 

当我们第一调用android.database.sqlite.SQLiteCursor的getCount()时,当前线程会锁定数据库,在该操作完成后才解锁。

其调用关系如下:
at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method) 
at android.database.sqlite.SQLiteQuery. fillWindow( SQLiteQuery.java:73) 
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:287) 
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:268) 
at android.widget.CursorAdapter. getCount (CursorAdapter.java:132) 
如果是第一次调用 SQLiteCursor 的 getCount () 的话,在getCount()中,它会调用 fillWindow (),
在SQLiteCursor的 fillWindow() 中,它又会调用的 fillWindow()
的相关 源码如下:
@Override
     public int getCount() {
         if (mCount == NO_COUNT) {
             fillWindow(0);
        }
         return mCount;
    }
 
     private void fillWindow ( int startPos) {
         if (mWindow == null) {
            // If there isn't a window set already it will only be accessed locally
            mWindow = new CursorWindow(true /* the window is local only */);
        }  else {
            mCursorState++;
                queryThreadLock();
                try {
                    mWindow.clear();
                } finally {
                    queryThreadUnlock();
                }
        }
        mWindow.setStartPosition(startPos);
        mCount =  mQuery.fillWindow(mWindow, mInitialRead, 0);
        // return -1 means not finished
         if (mCount == NO_COUNT){
            mCount = startPos + mInitialRead;
            Thread t = new Thread(new QueryThread(mCursorState), "query thread");
            t.start();
        } 
    }
在的 fillWindow() 中,它首先需要 lock数据库 ,然后调用JNI层的 native_fill_window() 进行数据库操作,在其操作完成之后才 unlock数据库 。
的相关源码如下:
/**
     * Reads rows into a buffer. This method acquires the database lock.
     *
     * @param window The window to fill into
     * @return number of total rows in the query
     */
    int fillWindow(CursorWindow window,
             int maxRead,  int lastPos) {
         long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
        mDatabase.logTimeStat(mSql, timeStart, SQLiteDatabase.GET_LOCK_LOG_PREFIX);
         try {
            acquireReference();
             try {
                window.acquireReference();
                // if the start pos is not equal to 0, then most likely window is
                // too small for the data set, loading by another thread
                // is not safe in this situation. the native code will ignore maxRead
                 int numRows =  native_fill_window(window, window.getStartPosition(), mOffsetIndex,
                        maxRead, lastPos);
 
                // Logging
                 if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
                    Log.d(TAG, "fillWindow(): " + mSql);
                }
                mDatabase.logTimeStat(mSql, timeStart);
                return numRows;
            }  catch (IllegalStateException e){
                // simply ignore it
                return 0;
            }  catch (SQLiteDatabaseCorruptException e) {
                mDatabase.onCorruption();
                throw e;
            }  finally {
                window.releaseReference();
            }
        } finally {
            releaseReference();
             mDatabase.unlock();
        }
    }
 
结束!

转载于:https://www.cnblogs.com/littlezan/p/3783815.html

你可能感兴趣的文章
第23月第24天 git命令 .git-credentials git rm --cached git stash clear
查看>>
java SE :标准输入/输出
查看>>
[ JAVA编程 ] double类型计算精度丢失问题及解决方法
查看>>
好玩的-记最近玩的几个经典ipad ios游戏
查看>>
PyQt5--EventSender
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
tmux的简单快捷键
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
php match_model的简单使用
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
STM32单片机使用注意事项
查看>>
移动开发平台-应用之星app制作教程
查看>>
leetcode 459. 重复的子字符串(Repeated Substring Pattern)
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
浅谈 unix, linux, ios, android 区别和联系
查看>>
51nod 1428 活动安排问题 (贪心+优先队列)
查看>>
latex for wordpress(一)
查看>>
如何在maven工程中加载oracle驱动
查看>>
Flask 系列之 SQLAlchemy
查看>>