標籤:android sqlite資料查詢結果 cursorwindow android cursorwindow
我們通過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));