Execute Query
When you execute the Query series function in the Sqlitedatabase class , only the queries are constructed and the query is not executed.
(Source tracking path for query)
Execute move (the Fillwindow inside is the place where the file handle is actually opened and the memory is allocated)
When you execute the cursor's move series function, the first execution creates a piece of shared memory for the query result set, which is Cursorwindow
Movetoposition Source Path
Fillwindow----really time-consuming place
The SQL statement is then executed to populate the shared memory with the data,
Fillwindow Source Path
In Sqlitecursor.java, you can see
1 @Override2 Public BooleanOnMove (intOldposition,intnewposition) {3 //Make sure the row at Newposition are present in the window4 if(Mwindow = =NULL|| Newposition < Mwindow.getstartposition () | |5Newposition >= (mwindow.getstartposition () +mwindow.getnumrows ())) {6 Fillwindow (newposition);7 }8 9 return true;Ten}
If the location of the requested query is within the scope of Cursorwindow, Fillwindow will not be executed.
And beyond the range of Cursorwindow, Fillwindow is called,
And in the Nativeexecuteforcursorwindow,
When fetching a record, Cursorwindow is emptied if the location to be requested exceeds the window range:
1Copyrowresult CPR =copyrow (env, window, statement, NumColumns, Startpos, addedrows); 2 if(CPR = = Cpr_full && addedrows && startpos + addedrows <Requiredpos) { 3 //we filled the window before we got to the one row we really wanted.4 //Clear the window and start filling it again from here. 5 //todo:would be nicer if we could progressively replace earlier rows. 6Window->Clear (); 7Window->Setnumcolumns (NumColumns); 8Startpos + =addedrows; 9Addedrows = 0; TenCPR =copyrow (env, window, statement, NumColumns, Startpos, addedrows); One}
Cursorwindow the emptying mechanism will affect the multithreading read (usually think not to read and write, SQLite concurrency is actually serial execution, but can be read concurrently, it is emphasized that multithreaded reading may also have problems), see later an article "ListView concurrent Read and write database."
Cursor
off (Explicit call to close () reason)
Tracking source to see close
1 //Sqlitecursor2 3 Super. Close ();4 synchronized( This) {5 mquery.close ();6 mdriver.cursorclosed ();7 }8 9 Ten //Abstractcursor One A Public voidClose () { -mclosed =true; - Mcontentobservable.unregisterall (); the ondeactivateorclose (); - } - - protected voidOndeactivateorclose () { + if(Mselfobserver! =NULL) { - Mcontentresolver.unregistercontentobserver (mselfobserver); +mselfobserverregistered =false; A } at mdatasetobservable.notifyinvalidated (); - } - - - //Abstractwindowedcursor - in /**@hide*/ - @Override to protected voidOndeactivateorclose () { + Super. Ondeactivateorclose (); - CloseWindow (); the } * $ protected voidCloseWindow () {Panax Notoginseng if(Mwindow! =NULL) { - mwindow.close (); theMwindow =NULL; + } A } the + - $ //sqliteclosable $ - Public voidClose () { - releasereference (); the } - Wuyi Public voidreleasereference () { the BooleanRefcountiszero =false; - synchronized( This) { WuRefcountiszero =--mreferencecount = = 0; - } About if(Refcountiszero) { $ onallreferencesreleased (); - } - } - A //Cursorwindow + the @Override - protected voidonallreferencesreleased () { $ Dispose (); the } the the Private voidDispose () { the if(Mcloseguard! =NULL) { - mcloseguard.close (); in } the if(Mwindowptr! = 0) { the Recordclosingofwindow (mwindowptr); About Nativedispose (mwindowptr); theMwindowptr = 0; the } the}
View Code
In the path associated with Cursorwindow, the final call Nativedispose () empties Cursorwindow;
When the cursor is reclaimed by GC, Finalize is called:
1 @Override2 protected voidFinalize () {3 Try {4 //if the cursor hasn ' t been closed yet, close it first5 if(Mwindow! =NULL) {6 if(Mstacktrace! =NULL) {7String sql =Mquery.getsql ();8 intLen =sql.length ();9 strictmode.onsqliteobjectleaked (Ten"Finalizing a Cursor that had not been deactivated or closed." + One"Database =" + Mquery.getdatabase (). Getlabel () + A", table =" + Medittable + -", query =" + sql.substring (0, (len > 1000)? 1000: Len), - mstacktrace); the } - close (); - } -}finally { + Super. Finalize (); - } +}
However, Finalize () did not release Cursorwindow, and Super.finalize (); It just untied the Observer and didn't release Cursorwindow .
So not calling Cursor.close () will eventually cause the shared memory (1M or 2M) in the Cursorwindow to leak.
From the source to see how SQLite in Android Read db