我们通过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));
手机扫一扫
移动阅读更方便
你可能感兴趣的文章