我们通过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应该是在客户端的创建出一个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是如何保存查询到的数据集的呢?

原理图如下:

没一行所对应的数据采用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));



更多相关文章

  1. android sharedpreference保存boolean,int,float,long,String和图片
  2. 深入了解android平台的jni(二)
  3. Mediaplayer中通过create函数获取资源时PreareAsync问题
  4. Android内存监测工具DDMS-->Heap
  5. Android程序开发通过HttpURLConnection上传文件到服务器
  6. android studio jks和eclipse keystore
  7. Android(安卓)自定义View - 网络加载 ProgressBar 加载与隐藏
  8. Android系统根目录结构及说明
  9. Android应用程序开发以及背后的设计思想深度剖析

随机推荐

  1. Android(安卓)图形系统之图形缓冲区分配
  2. Android触控基础:MotionEvent
  3. Android入门教程(四)之------Android工程
  4. Robotium入门
  5. 分析Content Providers用法【转】
  6. Android创建sdcard
  7. 简单实现android和wp聊天
  8. Android中自定义漂亮动态样式
  9. 从零开始学android开发-布局中 layout_gr
  10. Android(安卓)GestureDetector手势识别类