博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从源码看Android中sqlite是怎么读DB的(转)
阅读量:6204 次
发布时间:2019-06-21

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

执行query

执行SQLiteDatabase类中query系列函数时,只会构造查询信息,不会执行查询。

(query的源码追踪路径)

执行move(里面的fillwindow是真正打开文件句柄并分配内存的地方)

当执行Cursor的move系列函数时,第一次执行,会为查询结果集创建一块共享内存,即cursorwindow

moveToPosition源码路径

 

fillWindow----真正耗时的地方

然后会执行sql语句,向共享内存中填入数据,

fillWindow源码路径

在SQLiteCursor.java中可以看到

1 @Override 2 public boolean onMove(int oldPosition, int newPosition) { 3 // Make sure the row at newPosition is present in the window 4 if (mWindow == null || newPosition < mWindow.getStartPosition() || 5 newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) { 6 fillWindow(newPosition); 7 } 8 9 return true; 10 }

 

如果请求查询的位置在cursorWindow的范围内,不会执行fillWindow,

而超出cursorwindow的范围,会调用fillWindow,

而在nativeExecuteForCursorWindow中,

获取记录时,如果要请求的位置超出窗口范围,会发生CursorWindow的清空:

1 CopyRowResult 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 that 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. 6 window->clear(); 7 window->setNumColumns(numColumns); 8 startPos += addedRows; 9 addedRows = 0; 10 cpr = copyRow(env, window, statement, numColumns, startPos, addedRows); 11 }

 

CursorWindow的清空机制会影响到多线程读(通常认为不可以并发读写,sqlite的并发实际上是串行执行的,但可以并发读,这里要强调的是多线程读也可能有问题),具体见稍后一篇文章“listview并发读写数据库”。

 

Cursor关闭(显式调用close()的理由)

追踪源码看关闭

1  //SQLiteCursor 2  3 super.close(); 4 synchronized (this) { 5 mQuery.close(); 6 mDriver.cursorClosed(); 7 } 8 9 10 //AbstractCursor 11 12 public void close() { 13 mClosed = true; 14 mContentObservable.unregisterAll(); 15 onDeactivateOrClose(); 16 } 17 18 protected void onDeactivateOrClose() { 19 if (mSelfObserver != null) { 20 mContentResolver.unregisterContentObserver(mSelfObserver); 21 mSelfObserverRegistered = false; 22 } 23 mDataSetObservable.notifyInvalidated(); 24 } 25 26 27 //AbstractWindowedCursor 28 29 /** @hide */ 30 @Override 31 protected void onDeactivateOrClose() { 32 super.onDeactivateOrClose(); 33 closeWindow(); 34 } 35 36 protected void closeWindow() { 37 if (mWindow != null) { 38 mWindow.close(); 39 mWindow = null; 40 } 41 } 42 43 44 45 //SQLiteClosable 46 47 public void close() { 48 releaseReference(); 49 } 50 51 public void releaseReference() { 52 boolean refCountIsZero = false; 53 synchronized(this) { 54 refCountIsZero = --mReferenceCount == 0; 55 } 56 if (refCountIsZero) { 57 onAllReferencesReleased(); 58 } 59 } 60 61 //CursorWindow 62 63 @Override 64 protected void onAllReferencesReleased() { 65 dispose(); 66 } 67 68 private void dispose() { 69 if (mCloseGuard != null) { 70 mCloseGuard.close(); 71 } 72 if (mWindowPtr != 0) { 73 recordClosingOfWindow(mWindowPtr); 74 nativeDispose(mWindowPtr); 75 mWindowPtr = 0; 76 } 77 }
View Code

 

跟CursorWindow有关的路径里,最终调用nativeDispose()清空cursorWindow;

当Cursor被GC回收时,会调用finalize:

1 @Override 2 protected void finalize() { 3 try { 4 // if the cursor hasn't been closed yet, close it first 5 if (mWindow != null) { 6 if (mStackTrace != null) { 7 String sql = mQuery.getSql(); 8 int len = sql.length(); 9 StrictMode.onSqliteObjectLeaked( 10 "Finalizing a Cursor that has not been deactivated or closed. " + 11 "database = " + mQuery.getDatabase().getLabel() + 12 ", table = " + mEditTable + 13 ", query = " + sql.substring(0, (len > 1000) ? 1000 : len), 14 mStackTrace); 15 } 16 close(); 17 } 18 } finally { 19 super.finalize(); 20 } 21 }

 

然而finalize()并没有释放CursorWindow,而super.finalize();里也只是解绑了观察者,没有去释放cursorwindow

所以不调用cursor.close(),最终会导致cursorWindow所在的共享内存(1M或2M)泄露。

http://www.cnblogs.com/hellocwh/p/4924732.html

 

你可能感兴趣的文章
Oracle 10.2.0.5 非归档current redolog损坏处理一例
查看>>
Docker安装ssh,supervisor等基础工具
查看>>
Android项目里集成Cordova详解
查看>>
卡拉丁发布第四代车用空调滤清器
查看>>
三星:Android之外,技术为王
查看>>
技术回归本位:海尔引领空调产业重构格局
查看>>
Struts2中访问HttpServletRequest和HttpSession
查看>>
Android Fragments 详细使用
查看>>
解密阿里云七武器之高性能消息服务ONS
查看>>
三大纪律七项注意(Access数据库)
查看>>
Vlan中Trunk接口配置
查看>>
U盘 制作 win 7 64bit 旗舰版 安装盘
查看>>
一个行外人看中国的电子竞技
查看>>
项目实践中Linux集群的总结和思考
查看>>
自动加载缓存框架
查看>>
产品经理,你来自江湖
查看>>
关于tomcat Post 数据参数的问题
查看>>
计算机点滴
查看>>
Office 365 系列之九:配置和体验 Exchange 和 Lync
查看>>
Exchange 2016部署实施案例篇-04.Ex基础配置篇(下)
查看>>