我们通过Uri查询数据库所得到的数据集,保存在native层的CursorWindow中。CursorWindow的实质是共享内存的抽象,以实现跨进程数据共享。共享内存所採用的实现方式是文件映射。

在ContentProvider端透过SQLiteDatabase的封装查询到的数据集保存在CursorWindow所指向的共享内存中。然后通过Binder把这片共享内存传递到ContentResolver端,即查询端。

这样客户就能够通过Cursor来訪问这块共享内存中的数据集了。

那么CursorWindow是怎样实现的呢?

1.通过Create静态函数来创建

status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) {
String8 ashmemName("CursorWindow: ");
ashmemName.append(name);//文件名称 status_t result;
int ashmemFd = ashmem_create_region(ashmemName.string(), size);
if (ashmemFd < 0) {
result = -errno;
} else {
result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
if (result >= 0) {
void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);//文件映射
if (data == MAP_FAILED) {
result = -errno;
} else {
result = ashmem_set_prot_region(ashmemFd, PROT_READ);
if (result >= 0) {
CursorWindow* window = new CursorWindow(name, ashmemFd,
data, size, false /*readOnly*/);
result = window->clear();
if (!result) {
LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
"numRows=%d, numColumns=%d, mSize=%d, mData=%p",
window->mHeader->freeOffset,
window->mHeader->numRows,
window->mHeader->numColumns,
window->mSize, window->mData);
*outCursorWindow = window;
return OK;
}
delete window;
}
}
::munmap(data, size);
}
::close(ashmemFd);
}
*outCursorWindow = NULL;
return result;
}

2.通过文件句柄来创建。这样的case应该是在client的创建出一个CursorWindow所採用。

status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
String8 name = parcel->readString8(); status_t result;
int ashmemFd = parcel->readFileDescriptor();
if (ashmemFd == int(BAD_TYPE)) {
result = BAD_TYPE;
} else {
ssize_t size = ashmem_get_size_region(ashmemFd);
if (size < 0) {
result = UNKNOWN_ERROR;
} else {
int dupAshmemFd = ::dup(ashmemFd);
if (dupAshmemFd < 0) {
result = -errno;
} else {
void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
if (data == MAP_FAILED) {
result = -errno;
} else {
CursorWindow* window = new CursorWindow(name, dupAshmemFd,
data, size, true /*readOnly*/);
LOG_WINDOW("Created CursorWindow from parcel: freeOffset=%d, "
"numRows=%d, numColumns=%d, mSize=%d, mData=%p",
window->mHeader->freeOffset,
window->mHeader->numRows,
window->mHeader->numColumns,
window->mSize, window->mData);
*outCursorWindow = window;
return OK;
}
::close(dupAshmemFd);
}
}
}
*outCursorWindow = NULL;
return result;
}

CursorWindow是怎样保存查询到的数据集的呢?

原理图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU2FpbGluZ3RoaW5r/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

没一行所相应的数据採用FieldSlot数组来表示。

图中黄色部分表示一行所相应的数据。假设列所相应的数据是long或者double。那么就直接保存在FieldSlot中,假设是Blob或者String,那么就在FieldSlot中保存数据的廉价量。

FiledSlot的定义例如以下:

    struct FieldSlot {
private:
int32_t type;//列所相应的数据的类型
union {
double d;
int64_t l;
struct {
uint32_t offset;
uint32_t size;
} buffer;
} data;//data的数据类型是union,当type所表示的是String或者Blob的时候。offset表示的就是保存真实数据的buffer的偏移量。size表示buffer的大小 friend class CursorWindow;
} __attribute((packed));

Android native CursorWindow数据保存原理的更多相关文章

  1. [原理] Android Native内存泄漏检测原理解析

    转载请注明出处:https://www.cnblogs.com/zzcperf/articles/11615655.html 上一篇文章列举了不同版本Android OS内存泄漏的检测操作(传送门), ...

  2. Android中的数据保存

    形式 Android的数据保存分为3种形式:file, SharedPreference, Database 文件 主要思想就是通过Context类中提供的openFileInput和openFile ...

  3. React-Native系列Android——Native与Javascript通信原理(一)

    React-Native最核心的是Native与Javascript之间的通信,并且是双向通信.Native层到Javascript层,Javascript层到Native层.虽说是两个方向,但实现上 ...

  4. android中Json数据保存方式

    package com.example.savejsonproject; import java.io.File; import java.io.FileNotFoundException; impo ...

  5. Android数据保存之SharedPreference

    前言: 程序中处理的大部分问题都与数据有关,读取数据显示在UI上,读取的数据可以是本地的,也可以是网络的.保存用户数据到存储空间,可以是本地的数据库,文件等,也可以是保存到网络服务器.总之大部分的程序 ...

  6. Android应用程序组件Content Provider在应用程序之间共享数据的原理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6967204 在Android系统中,不同的应用 ...

  7. Android Native -- Message/Handler/Looper机制(原理篇)

    ⌈Android Native消息队列处理系列文章⌋ Android Native -- Message/Handler/Looper机制(原理篇) Android Native -- Message ...

  8. Android少量数据保存之SharedPreferences接口实例

    SharedPreferences数据保存主要是通过键值的方式存储在xml文件中 xml文件在data/此程序的包名/XX.xml 格式 <?xml version='1.0' encoding ...

  9. Android数据存储(1)少量数据保存之SharedPreferences接口实例

    SharedPreferences数据保存主要是通过键值的方式存储在xml文件中 xml文件在data/此程序的包名/XX.xml 格式 <?xml version='1.0' encoding ...

随机推荐

  1. c#基于udp实现的p2p语音聊天工具

    原创性申明 此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/40124773假设进行转载请注明出处.本文作者原创,邮箱zhujunx ...

  2. C++表达式求值(利用数据结构栈)

    唉,刚刚用C++又又一次写了一个较完好的表达式求值程序,最后精简后程序还不到100行.这不经让我 想到了大一上学期刚学c语言时自己费了好大的劲,写了几百行并且功能还不是非常齐全(当时还不能计算有括号的 ...

  3. UI各种小控件的用法

    今天给大家列举出来UI中的一些小控件的用法.方便大的学习与使用 一些方法和属性我们能够查看API文档.不必将每一个控件的功能都记住, 由于在使用的过程中,我们能够查看API文档.方便使用,我们仅仅要记 ...

  4. Android Cocos2dx引擎 prv.ccz/plist/so等优化缓存文件,手把手ida教你逆向project反编译apk库等文件

    前段时间在 Android play 上看到一个非常牛逼的 3D 动态天气预报,效果真的非常炫.二话不说动手 dex2jar.bat/apktool 发现这并没 有什么卵用,在核心的地方看见 nati ...

  5. Oracle 查看锁定表用户的SQL

    #描述:当执行如下SQL select * From XXX for Updata 发现表“XXX”被锁定 #只需要执行如下SQL 查看锁定该表的用户 SELECT object_name, mach ...

  6. C#读出文本文件内容,遍历数组筛选出 含有汉字对应的拼音字符

    情景描述:由于任务需要,现有一用户表数据,用户名 字段 在新增用户时,输入中文和拼音两种,先要区分同时含有中文和拼音字母的用户名.由于数据很多,可以通过一段代码完成查询: 前提:在阅读本文之前可以先了 ...

  7. 阿里云服务器用Docker配置运行nginx并访问

    一.Docker拉取nginx镜像 docker pull nginx:1.12.2 这里是下载的是nginx的1.12.2版本,其他版本的镜像请访问https://hub.docker.com/r/ ...

  8. 转:Eclipse上安装GIT插件EGit及使用

    一.Eclipse上安装GIT插件EGit Eclipse的版本eclipse-java-helios-SR2-win32.zip(在Eclipse3.3版本找不到对应的 EGit插件,无法安装) E ...

  9. HDU 2037 今年暑假不AC【贪心】

    解题思路:即为给出一个总长度确定的区间,再输入不同的子区间,求在这个总区间里面包含的不相交的子区间最多有多少个. 可以由最特殊的情况来想,即给出的这些子区间现在都不相交,比如 ----- (1,3)  ...

  10. POJ 2524 Ubiquitous Religions 【并查集】

    解题思路:输入总人数 n,和m组数据:即和杭电畅通工程相类似,对这m组数据做合并操作后,求最后一共有多少块区域. #include<stdio.h> int pre[50001]; int ...