SQLite cursor.moveToNext()

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.SQLiteCursorgetCount()时,当前线程会锁定数据库,在该操作完成后才解锁。

其调用关系如下
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()
中,它又会调用SQLiteQuery
fillWindow()
android.database.sqlite.SQLiteCursor
的相关
源码如下: @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();         }      }
SQLiteQuery
fillWindow()
中,它首先需要
lock数据库
,然后调用JNI层的
native_fill_window()
进行数据库操作,在其操作完成之后才
unlock数据库

android.database.sqlite.SQLiteQuery
的相关源码如下:
/**
     * 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();         }     }  
结束!

    原文作者:sqlite
    原文地址: https://www.cnblogs.com/littlezan/p/3783815.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞