从源码看Android中sqlite是怎么通过cursorwindow读DB的
更多内容在这里查看
https://ahangchen.gitbooks.io/windy-afternoon/content/
执行query
执行SQLiteDatabase类中query系列函数时,只会构造查询信息,不会执行查询。

(query的源码追踪路径)
执行move(里面的fillwindow是真正打开文件句柄并分配内存的地方)
当执行Cursor的move系列函数时,第一次执行,会为查询结果集创建一块共享内存,即cursorwindow

moveToPosition源码路径
fillWindow----真正耗时的地方
然后会执行sql语句,向共享内存中填入数据,

fillWindow源码路径
在SQLiteCursor.java中可以看到
@Override
public boolean onMove(int oldPosition, int newPosition) {
// Make sure the row at newPosition is present in the window
if (mWindow == null || newPosition < mWindow.getStartPosition() ||
newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
fillWindow(newPosition);
} return true;
}
如果请求查询的位置在cursorWindow的范围内,不会执行fillWindow,
而超出cursorwindow的范围,会调用fillWindow,
而在nativeExecuteForCursorWindow中,
获取记录时,如果要请求的位置超出窗口范围,会发生CursorWindow的清空:
CopyRowResult cpr = copyRow(env, window, statement, numColumns, startPos, addedRows);
if (cpr == CPR_FULL && addedRows && startPos + addedRows < requiredPos) {
// We filled the window before we got to the one row that we really wanted.
// Clear the window and start filling it again from here.
// TODO: Would be nicer if we could progressively replace earlier rows.
window->clear();
window->setNumColumns(numColumns);
startPos += addedRows;
addedRows = 0;
cpr = copyRow(env, window, statement, numColumns, startPos, addedRows);
}
CursorWindow的清空机制会影响到多线程读(通常认为不可以并发读写,sqlite的并发实际上是串行执行的,但可以并发读,这里要强调的是多线程读也可能有问题),具体见稍后一篇文章“listview并发读写数据库”。
上面说的这些直观的感受是什么样的呢?大概是这样,
执行query,读10000条数据,很快就拿到了cursor,这里不会卡,
执行moveToFirst,卡一下(fillwindow(0))
moveToPosition(7500),卡一下,因为已经超了cursorwindow的区域,又去fillwindow(7500),
关于fillwindow还有一些奇特的细节,比如4.0以后,fillwindow会填充position前后各一段数据,防止读旧数据的时候又需要fill,感兴趣的同学可以看看各个版本fillwidow的源码。
这里还可以延伸一下,因为高版本的android sqlite对旧版有许多改进,
所以实际开发里我们有时候会把sqlite的源码带在自己的工程里,使得低版本的android也可以使用高版本的特性,并且避开一部分兼容性问题。
Cursor关闭(显式调用close()的理由)
追踪源码看关闭
//SQLiteCursor super.close();
synchronized (this) {
mQuery.close();
mDriver.cursorClosed();
} //AbstractCursor public void close() {
mClosed = true;
mContentObservable.unregisterAll();
onDeactivateOrClose();
} protected void onDeactivateOrClose() {
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
mSelfObserverRegistered = false;
}
mDataSetObservable.notifyInvalidated();
} //AbstractWindowedCursor /** @hide */
@Override
protected void onDeactivateOrClose() {
super.onDeactivateOrClose();
closeWindow();
} protected void closeWindow() {
if (mWindow != null) {
mWindow.close();
mWindow = null;
}
} //SQLiteClosable public void close() {
releaseReference();
} public void releaseReference() {
boolean refCountIsZero = false;
synchronized(this) {
refCountIsZero = --mReferenceCount == 0;
}
if (refCountIsZero) {
onAllReferencesReleased();
}
} //CursorWindow @Override
protected void onAllReferencesReleased() {
dispose();
} private void dispose() {
if (mCloseGuard != null) {
mCloseGuard.close();
}
if (mWindowPtr != 0) {
recordClosingOfWindow(mWindowPtr);
nativeDispose(mWindowPtr);
mWindowPtr = 0;
}
}
跟CursorWindow有关的路径里,最终调用nativeDispose()清空cursorWindow;
当Cursor被GC回收时,会调用finalize:
@Override
protected void finalize() {
try {
// if the cursor hasn't been closed yet, close it first
if (mWindow != null) {
if (mStackTrace != null) {
String sql = mQuery.getSql();
int len = sql.length();
StrictMode.onSqliteObjectLeaked(
"Finalizing a Cursor that has not been deactivated or closed. " +
"database = " + mQuery.getDatabase().getLabel() +
", table = " + mEditTable +
", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
mStackTrace);
}
close();
}
} finally {
super.finalize();
}
}
然而finalize()并没有释放CursorWindow,而super.finalize();里也只是解绑了观察者,没有去释放cursorwindow
所以不调用cursor.close(),最终会导致cursorWindow所在的共享内存(1M或2M)泄露。
从源码看Android中sqlite是怎么通过cursorwindow读DB的的更多相关文章
- 从源码看Android中sqlite是怎么读DB的(转)
执行query 执行SQLiteDatabase类中query系列函数时,只会构造查询信息,不会执行查询. (query的源码追踪路径) 执行move(里面的fillwindow是真正打开文件句柄并分 ...
- Android so 文件进阶<二> 从dlsym()源码看android 动态链接过程
0x00 前言 这篇文章其实是我之前学习elf文件关于符号表的学习笔记,网上也有很多关于符号表的文章,怎么说呢,感觉像是在翻译elf文件格式的文档一样,千篇一律,因此把自己的学习笔记分享出来.dls ...
- 源码解析Android中View的measure量算过程
Android中的Veiw从内存中到呈现在UI界面上需要依次经历三个阶段:量算 -> 布局 -> 绘图,关于View的量算.布局.绘图的总体机制可参见博文< Android中View ...
- 从源码看java中Integer的缓存问题
在开始详细的说明问题之前,我们先看一段代码 public static void compare1(){ Integer i1 = 127, i2 = 127, i3 = 128, i4 = 128; ...
- 从源码看 Vue 中的 Mixin
最近在做项目的时候碰到了一个奇怪的问题,通过 Vue.mixin 方法注入到 Vue 实例的一个方法不起作用了,后来经过仔细排查发现这个实例自己实现了一个同名方法,导致了 Vue.mixin 注入方法 ...
- 从 php 源码看 php 中的对象
从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...
- 将Android源码导入eclipse中的方法以及编译Android源码指定模块
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53365659 将android源码导入eclipse.androidstudio. ...
- 从微信小程序开发者工具源码看实现原理(一)- - 小程序架构设计
使用微信小程序开发已经很长时间了,对小程序开发已经相当熟练了:但是作为一名对技术有追求的前端开发,仅仅熟练掌握小程序的开发感觉还是不够的,我们应该更进一步的去理解其背后实现的原理以及对应的考量,这可能 ...
- 从源码看commit和commitAllowingStateLoss方法区别
Fragment介绍 在很久以前,也就是我刚开始写Android时(大约在2012年的冬天--),那时候如果要实现像下面微信一样的Tab切换页面,需要继承TabActivity,然后使用TabHost ...
随机推荐
- C/S ASP.NET页面传值汇总
一. QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法.但是对于传递数组或对象的话,就不 ...
- Linux命令--链接文件的那些事
linux 链接ln的使用 linux操作系统下ln的使用方式: ln [option] source_file dest_file #source_file是待建立链接文件的文件,dest_file ...
- hql中in的用法
平时经常用Hibernate,由于习惯表间不建立关联,所以HQL查询时候经常要用in语句. 由于表间没有建立外键的关联关系所以使用in是最常见的代替使用对象po中的set. 但是在写hql时如果在ne ...
- python基础教程第2章——列表与元组笔记
1.序列是Python中最基本的数据结构.序列中的每个元素被分配一个序列号——元素的位置,也称索引,第1个索引是0,第2为1,以此类推.序列中的最后1个元素为-1,倒数第2个位-2. python中有 ...
- Amazon MWS 上传数据 (三) 提交请求
前面介绍了设置服务和构造请求,现在介绍提交请求. 上传数据,查询上传操作的工作状态,和处理上传操作返回的报告操作使用的Amazon API 分别为:SubmitFeed(),FeedSubmissio ...
- win7下设置 WiFi AP
开启windows 7的隐藏功能:虚拟WiFi和SoftAP(即虚拟无线AP),就可以让计算机变成无线路由器.实现共享上网. 1.以管理员身份运行命令提示符: “开始”---在搜索栏输入“cmd”-- ...
- JVM内存分配和回收
本文内容来自<Java编程思想(第四版)>第二章<一切都是对象>和第五章<初始化与清理>.作为一个使用了好几年的Javaer,再次看编程思想的前面章节(不要问我为什 ...
- ARM 7 用户模式下禁止/使能中断的一种方法--使用软中断 for Keil MDK
最近写一个程序,需要在用户模式下关中断,但ARM 7的体系结构决定了中断必须在特权模式下才可以更改,所以想到使用ARM的软中断来实现关中断和开中断. 使用软中断,首先要有硬件指令的支持.ARM有条指令 ...
- layout_weight 的解释及使用
layout_weight 的解释及使用 转自:http://my.oschina.net/jsan/blog/191492 在Android的控件布局中,有一个奇葩的 layout_weight 属 ...
- 谷歌page speed 安装使用及页面问题详解
原文地址:http://wenku.baidu.com/view/b0a61f3ebcd126fff7050b40.html 谷歌page speed 安装使用及页面问题详解 谷歌page speed ...