gpt4 book ai didi

android - 在进程之间传递游标(Parcelable Cursor)

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:48:32 24 4
gpt4 key购买 nike

我需要将 Cursor (SQLiteCursor) 从服务传递到 API 10 上的应用程序,并且很难找到一个像样的(和快速)解决方案。

我看过 CursorWindow 类。这是 Parcelable 但我无法在 API 10 上实例化此类以使用 SQLiteCursor.fillWindow() 因为它没有有效的构造函数。 CursorWindow(boolean) 已弃用。

即使我得到一个包含来自 SQLiteCursor 的数据的 CursorWindow 实例,我如何将这个窗口复制到一个新的 Cursor 中?我应该为此使用什么 Cursor 实现?我看不到扩展 AbstractWindowedCursor 的可用 Cursor

感谢您的宝贵时间!

最佳答案

我实现了一个 ParcelableCursor 类,它实现了 CrossProcessCursorParcelable 接口(interface)。如果有人感兴趣,我会发布它。一些操作还不支持/实现,以及使用自定义 BijectiveMap(这很容易实现)。

/**
* Prefer ParcelableCursorForIntent instead.<br/>
* Cursor for IPC. Takes a CursorWindow as data buffer and the number of columns
* that CursorWindow has.<br/>
* <br/>
* <b>NOTE: this Cursor cannot be parceled when sending by intents due to <a
* href="http://code.google.com/p/android/issues/detail?id=4470">an Android
* bug</a>. Please use ParcelableCursorForIntent instead.</b>
*
* @author m0skit0@blablabla.eu
*
*/
public class ParcelableCursor implements Parcelable, CrossProcessCursor {

/** Cursor data window */
protected CursorWindow window = CursorHelper.getCursorWindowInstance();

/** How many columns we have */
protected int numColumns = 0;

/** Column names */
protected BijectiveMap<String, Integer> colNames = new BijectiveHashMap<String, Integer>();

/** Current row */
protected int curRow = -1;

/** Is this cursor closed? */
protected boolean closed = false;

/** CREATOR for Parcelable */
public static final Parcelable.Creator<ParcelableCursor> CREATOR = new Parcelable.Creator<ParcelableCursor>() { // NOPMD
// AM
@Override
public ParcelableCursor createFromParcel(final Parcel in) {
return new ParcelableCursor(in);
}

@Override
public ParcelableCursor[] newArray(final int size) {
return new ParcelableCursor[size];
}
};

/**
* Creates an empty ParcelableCursor. Please consider to use
* {@link #setFromCursor(AbstractWindowedCursor)} or
* {@link #setFromWindow(CursorWindow)} to initialize it.
*/
public ParcelableCursor() {
// Empty ParcelableCursor, don't forget to use #setFromCursor
}

/** Constructor for Parcelable */
public ParcelableCursor(final Parcel in) {
readFromParcel(in); // NOPMD by yasin on 12/7/12 11:55 AM - Android's
// Parceleble
}

/**
* Adds a new column at the end and assigns it this name. This will make
* this cursor to lose all its data, so you have to add all the columns
* before adding any row.
*/
private void addColumn(final String name) {
this.numColumns++;
this.curRow = -1;
this.colNames.put(name, this.numColumns - 1);
}

@Override
public void close() {
this.window.close();
this.closed = true;
}

@Override
public void copyStringToBuffer(final int columnIndex,
final CharArrayBuffer buffer) {
// TODO: what does this do?
}

@Override
public void deactivate() {
// Deprecated, does nothing
}

@Override
public int describeContents() {
// Nothing to do here
return 0;
}

@Override
public void fillWindow(final int position, final CursorWindow window) {
CursorHelper.copyCursorWindow(position, this.window, window);
}

@Override
public byte[] getBlob(final int columnIndex) {
return this.window.getBlob(this.curRow, columnIndex);
}

@Override
public int getColumnCount() {
return this.numColumns;
}

@Override
public int getColumnIndex(final String columnName) {
int ret = -1;
final Integer col = this.colNames.get(columnName);
if (col != null) {
ret = col;
}
return ret;
}

@Override
public int getColumnIndexOrThrow(final String columnName)
throws IllegalArgumentException {
final Integer col = this.colNames.get(columnName);
if (col == null) {
throw new IllegalArgumentException();
}
return col;
}

@Override
public String getColumnName(final int columnIndex) {
return this.colNames.getKey(columnIndex);
}

@Override
public String[] getColumnNames() {
if (DebugConfig.DEBUG) {
Log.d("PARCELCURSOR.getColumnNames()---", "===GETTING COLNAMES===");
}

final Set<Entry<String, Integer>> set = this.colNames.entrySet();
final String[] colArray = new String[set.size()];
for (final String colName : this.colNames.keySet()) {
if (DebugConfig.DEBUG) {
Log.d("-------------PARCELCURSOR.getColumnNames()", colName);
}
final int pos = this.colNames.get(colName);
colArray[pos] = colName;
}

return colArray;
}

@Override
public int getCount() {
return this.window.getNumRows();
}

@Override
public double getDouble(final int columnIndex) {
return this.window.getDouble(this.curRow, columnIndex);
}

@Override
public Bundle getExtras() {
// Does not support Extras
return null;
}

@Override
public float getFloat(final int columnIndex) {
return this.window.getFloat(this.curRow, columnIndex);
}

@Override
public int getInt(final int columnIndex) {
return this.window.getInt(this.curRow, columnIndex);
}

@Override
public long getLong(final int columnIndex) {
return this.window.getLong(this.curRow, columnIndex);
}

@Override
public int getPosition() {
return this.curRow;
}

@Override
public short getShort(final int columnIndex) { // NOPMD by yasin on 12/7/12
// 11:57 AM - Override
return this.window.getShort(this.curRow, columnIndex);
}

@Override
public String getString(final int columnIndex) {
return this.window.getString(this.curRow, columnIndex);
}

@SuppressLint("NewApi")
@Override
public int getType(final int columnIndex) {
final int currentapiVersion = android.os.Build.VERSION.SDK_INT;

int result = 0;

if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
result = this.window.getType(this.curRow, columnIndex);
} else {
if (this.window.isNull(this.curRow, columnIndex)) {
result = 0; // FIELD_TYPE_NULL;
} else if (this.window.isFloat(this.curRow, columnIndex)) {
result = 2; // FIELD_TYPE_FLOAT;
} else if (this.window.isLong(this.curRow, columnIndex)) {
result = 1; // FIELD_TYPE_INTEGER;
} else if (this.window.isString(this.curRow, columnIndex)) {
result = 3; // FIELD_TYPE_STRING;
} else if (this.window.isBlob(this.curRow, columnIndex)) {
result = 4; // FIELD_TYPE_BLOB;
}
}

return result;
}

@Override
public boolean getWantsAllOnMoveCalls() {
return false;
}

@Override
public CursorWindow getWindow() {
final CursorWindow ret = CursorHelper.getCursorWindowInstance();
fillWindow(0, ret);
return ret;
}

@Override
public boolean isAfterLast() {
return (this.curRow >= this.window.getNumRows());
}

@Override
public boolean isBeforeFirst() {
return (this.curRow < 0);
}

@Override
public boolean isClosed() {
return this.closed;
}

@Override
public boolean isFirst() {
return (this.curRow == 0);
}

@Override
public boolean isLast() {
return (this.curRow == this.window.getNumRows() - 1);
}

@Override
public boolean isNull(final int columnIndex) {
return this.getType(columnIndex) == FIELD_TYPE_NULL;
}

@Override
public boolean move(final int offset) {
final int oldPos = this.curRow;
this.curRow += offset;
if (this.curRow < -1) {
this.curRow = -1;
return false;
} else if (this.curRow > this.window.getNumRows() - 1) {
this.curRow = this.window.getNumRows() - 1;
return false;
}
return onMove(oldPos, this.curRow);
}

@Override
public boolean moveToFirst() {
if (this.window.getNumRows() == 0) {
return false;
}
final int oldPos = this.curRow;
this.curRow = 0;
return onMove(oldPos, this.curRow);
}

@Override
public boolean moveToLast() {
if (this.window.getNumRows() == 0) {
return false;
}
final int oldPos = this.curRow;
this.curRow = this.window.getNumRows() - 1;
return onMove(oldPos, this.curRow);
}

@Override
public boolean moveToNext() {
final int oldPos = this.curRow++;
if (isAfterLast()) {
this.curRow = this.window.getNumRows();
return false;
}
return onMove(oldPos, this.curRow);
}

@Override
public boolean moveToPosition(final int position) {
if (position < -1 && position >= this.window.getNumRows()) {
return false;
}
final int oldPos = this.curRow;
this.curRow = position;
return onMove(oldPos, this.curRow);
}

@Override
public boolean moveToPrevious() {
final int oldPos = this.curRow--;
if (isBeforeFirst()) {
this.curRow = -1;
return false;
}
return onMove(oldPos, this.curRow);
}

@Override
public boolean onMove(final int oldPosition, final int newPosition) {
// Don't forget to set curRow = -1 if this method returns false
return true;
}

/** Restoring this object from a Parcel */
public void readFromParcel(final Parcel in) {

this.numColumns = in.readInt();
this.colNames = in.readParcelable(ClassLoaderHelper.getClassLoader());
this.curRow = in.readInt();
this.closed = (in.readByte() == 1);
// Closes the cursor before create a new cursor.
if (window != null) {
window.close();
}
this.window = CursorWindow.newFromParcel(in);
}

/** Not supported */
@Override
public void registerContentObserver(final ContentObserver observer) {
// Does nothing
}

/** Not supported */
@Override
public void registerDataSetObserver(final DataSetObserver observer) {
// Does nothing
}

/** Deprecated, not supported */
@Override
public boolean requery() {
return false;
}

/** Not supported */
@Override
public Bundle respond(final Bundle extras) {
// Does nothing
return null;
}

/** Sets this cursor from another windowed Cursor */
public void setFromCursor(final AbstractWindowedCursor cursor) throws CursorIndexOutOfBoundsException, IllegalStateException {

// Reset number of columns
this.numColumns = 0;

// Set column names
final String[] colNames = cursor.getColumnNames();
if (colNames != null) {
for (final String col : colNames) {
addColumn(col);
}
}

// Fill window
this.window.clear();
this.window.setNumColumns(this.numColumns);
cursor.fillWindow(0, this.window);
moveToPosition(-1);
}

/** Sets this cursor from another windowed Cursor */
public void setFromCursor(final MatrixCursor cursor) throws CursorIndexOutOfBoundsException ,IllegalStateException{

// Reset number of columns
this.numColumns = 0;

// Set column names
final String[] colNames = cursor.getColumnNames();
if (colNames != null) {
for (final String col : colNames) {
addColumn(col);
}
}

// Fill window
this.window.clear();
this.window.setNumColumns(this.numColumns);
cursor.fillWindow(0, this.window);
moveToPosition(-1);
}

/** Sets this cursor using a CursorWindow data */
public void setFromWindow(final CursorWindow window) {
CursorHelper.copyCursorWindow(0, window, this.window);
this.numColumns = CursorHelper.getCursorWindowNumCols(window);
moveToPosition(-1);
}

/** Not supported */
@Override
public void setNotificationUri(final ContentResolver cr, final Uri uri) {
// Does nothing
}

/** Not supported */
@Override
public void unregisterContentObserver(final ContentObserver observer) {
// Does nothing
}

/** Not supported */
@Override
public void unregisterDataSetObserver(final DataSetObserver observer) {
// Does nothing
}

@Override
public void writeToParcel(final Parcel out, final int flags) {

out.writeInt(this.numColumns);
out.writeParcelable((Parcelable) this.colNames, 0);
out.writeInt(this.curRow);
out.writeByte(this.closed ? (byte) 1 : 0);
this.window.writeToParcel(out, flags);
}

}

仍在寻找更标准的方法来做到这一点。任何信息将不胜感激!

编辑:这通过了很少的测试,所以在使用之前测试它。

EDIT2:事实上,它充满了错误......我会尽快更新一个错误较少的版本。

EDIT3:更新了我们使用一年以来的工作光标。

关于android - 在进程之间传递游标(Parcelable Cursor),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11790893/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com