执行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 }

跟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

从源码看Android中sqlite是怎么读DB的(转)的更多相关文章

  1. 从源码看Android中sqlite是怎么通过cursorwindow读DB的

    更多内容在这里查看 https://ahangchen.gitbooks.io/windy-afternoon/content/ 执行query 执行SQLiteDatabase类中query系列函数 ...

  2. Android so 文件进阶<二> 从dlsym()源码看android 动态链接过程

    0x00  前言 这篇文章其实是我之前学习elf文件关于符号表的学习笔记,网上也有很多关于符号表的文章,怎么说呢,感觉像是在翻译elf文件格式的文档一样,千篇一律,因此把自己的学习笔记分享出来.dls ...

  3. 源码解析Android中View的measure量算过程

    Android中的Veiw从内存中到呈现在UI界面上需要依次经历三个阶段:量算 -> 布局 -> 绘图,关于View的量算.布局.绘图的总体机制可参见博文< Android中View ...

  4. 从源码看java中Integer的缓存问题

    在开始详细的说明问题之前,我们先看一段代码 public static void compare1(){ Integer i1 = 127, i2 = 127, i3 = 128, i4 = 128; ...

  5. 从源码看 Vue 中的 Mixin

    最近在做项目的时候碰到了一个奇怪的问题,通过 Vue.mixin 方法注入到 Vue 实例的一个方法不起作用了,后来经过仔细排查发现这个实例自己实现了一个同名方法,导致了 Vue.mixin 注入方法 ...

  6. 从 php 源码看 php 中的对象

    从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...

  7. 将Android源码导入eclipse中的方法以及编译Android源码指定模块

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53365659 将android源码导入eclipse.androidstudio. ...

  8. 从微信小程序开发者工具源码看实现原理(一)- - 小程序架构设计

    使用微信小程序开发已经很长时间了,对小程序开发已经相当熟练了:但是作为一名对技术有追求的前端开发,仅仅熟练掌握小程序的开发感觉还是不够的,我们应该更进一步的去理解其背后实现的原理以及对应的考量,这可能 ...

  9. 从源码看commit和commitAllowingStateLoss方法区别

    Fragment介绍 在很久以前,也就是我刚开始写Android时(大约在2012年的冬天--),那时候如果要实现像下面微信一样的Tab切换页面,需要继承TabActivity,然后使用TabHost ...

随机推荐

  1. c#并行任务多种优化方案分享(异步委托)

    遇到一个多线程任务优化的问题,现在解决了,分享如下. 假设有四个任务: 任务1:登陆验证(CheckUser) 任务2:验证成功后从Web服务获取数据(GetDataFromWeb) 任务3:验证成功 ...

  2. MVC快速分页

    .NET手记-ASP.NET MVC快速分页的实现   对于Web应用,展示List是很常见的需求,随之而来的常见的分页组件.jQuery有现成的分页组件,网上也有着大量的第三方分页组件,都能够快速实 ...

  3. Install Oracle 11gR2 on Debian wheezy(转)

    Install Oracle 11gR2 on Debian wheezy 出处:http://gaiustech.wordpress.com/2013/06/26/howto-install-ora ...

  4. 安装gcc 3.4

    安装   gcc 3.4 f**k,不是为了编译0.11内核.我才懒得鸟3.4的版本号 源代码编译被我实践--"不归路",各种报错,我起码不止是了4个版本号的gcc,各种不兼容.各 ...

  5. 创建Material Design风格Android应用--自定义阴影和裁剪视图

    之前已经写过通过应用主题和使用ListView, CardView,应用Material Design样式,同一时候都都能够通过support library向下兼容.今天要写的阴影和视图裁剪.无法向 ...

  6. VS找不到约束

    [问题叙述性说明] watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3hsMDkyMQ==/font/5a6L5L2T/fontsize/400/fill/ ...

  7. JS call与apply

    JS的call与apply call和apply是JS中比较重要的两个方法, 一般在框架和组件设计中用的较多,比如jQuery Code. 那么这两个方法是做什么的呢,下面我们通过代码来了解: 1 f ...

  8. C#和C++下数据类型对应表

    /C++中的DLL函数原型为//extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsigned char ...

  9. Android ImageView分析并展开

    版本号:1.0  日期:2014.6.11 2014.6.12 版权:© 2014 kince 转载注明出处   ImageView是开发中经常使用到的一个控件,也能够说是不可缺少的. 对于它的使用. ...

  10. 在高德地图应用api,和api展出的标记小的应用程序

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...