Android 从消息和ContentProvider调用时,光标行为会发生变化
我有这个游标实现(API 10): 在这里,当我在Android 从消息和ContentProvider调用时,光标行为会发生变化,android,cursor,ipc,Android,Cursor,Ipc,我有这个游标实现(API 10): 在这里,当我在ContentProvider进程上运行时,isNull()方法工作正常,但是当客户端进程接收到光标时,它总是返回false 这是我执行Cursor.getString()时引发的异常,因为Cursor.isNull()返回(错误)false: 08-13 13:17:16.480: D/SELECT on ui(1572): java.lang.IllegalStateException: UNKNOWN type 0 08-13 13:17:
ContentProvider
进程上运行时,isNull()
方法工作正常,但是当客户端进程接收到光标时,它总是返回false
这是我执行Cursor.getString()
时引发的异常,因为Cursor.isNull()
返回(错误)false
:
08-13 13:17:16.480: D/SELECT on ui(1572): java.lang.IllegalStateException: UNKNOWN type 0
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWindow.getString_native(Native Method)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWindow.getString(CursorWindow.java:329)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:49)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWrapper.getString(CursorWrapper.java:135)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.blablabla.android.core.test.TestDBActivity.selectDB(TestDBActivity.java:332)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.blablabla.android.core.test.TestDBActivity$3.onClick(TestDBActivity.java:169)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.view.View.performClick(View.java:2485)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.view.View$PerformClick.run(View.java:9080)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Handler.handleCallback(Handler.java:587)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Handler.dispatchMessage(Handler.java:92)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Looper.loop(Looper.java:123)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-13 13:17:16.480: D/SELECT on ui(1572): at java.lang.reflect.Method.invokeNative(Native Method)
08-13 13:17:16.480: D/SELECT on ui(1572): at java.lang.reflect.Method.invoke(Method.java:507)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-13 13:17:16.480: D/SELECT on ui(1572): at dalvik.system.NativeStart.main(Native Method)
EDIT:经过大量调试后,我可以看到当值为null
时,isBlob()
返回true
你知道这里可能出了什么问题吗?问题实际上出在CursorHelper.copyCursorWindow()
,它是通过fillWindow()
调用的,Android系统在CursorWrapper
中调用它。这是我对这个方法的错误版本:
/**
* Copies one CursorWindow into another. Previous data in destination
* CursorWindow is lost
*
* @param position
* Starting position to copy from the origin window
* @param numColumns
* Number of columns in the origin window
* @param origin
* CursorWindow to copy from
* @param destination
* CursorWindow to copy to
*/
public static void copyCursorWindow(int position, CursorWindow origin,
CursorWindow destination) {
// Column number
int numCols = getCursorWindowNumCols(origin);
// Clear destination
destination.clear();
destination.setNumColumns(numCols);
// Rows
int i = position;
while (i < origin.getNumRows() && destination.allocRow()) {
// Columns
for (int j = 0; j < numCols; j++) {
if (origin.isBlob(i, j)) {
byte[] cur = origin.getBlob(i, j);
destination.putBlob(cur, i, j);
} else if (origin.isFloat(i, j)) {
Float cur = origin.getFloat(i, j);
destination.putDouble(cur, i, j);
} else if (origin.isLong(i, j)) {
Long cur = origin.getLong(i, j);
destination.putLong(cur, i, j);
} else if (origin.isString(i, j)) {
String cur = origin.getString(i, j);
destination.putString(cur, i, j);
} else if (origin.isNull(i, j)) {
destination.putNull(i, j);
}
}
i++;
}
}
这是如何实现isBlob()
的一个(恼人的)错误(虽然在API 11+中可能已修复,因为这部分有一些更改,比如Cursor.getType()
method-)
()实现与SQLiteCursor
impl之间的主要区别。我可以看到的是您的#getWindow()
实现,例如,一个AbstractWindowedCursor
子类不会不断创建新的窗口,而是保留一个实例。您的意思是我应该返回此对象拥有的CursorWindow
?但如果其他对象使用此方法以意外的方式更改CursorWindow
内容,则这可能是不可预测的。这与isNull()
工作不正常也有什么关系?我看不到这个关系,我把它改成了简单的返回窗口代码>仍然是相同的问题。
08-13 13:17:16.480: D/SELECT on ui(1572): java.lang.IllegalStateException: UNKNOWN type 0
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWindow.getString_native(Native Method)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWindow.getString(CursorWindow.java:329)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:49)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.database.CursorWrapper.getString(CursorWrapper.java:135)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.blablabla.android.core.test.TestDBActivity.selectDB(TestDBActivity.java:332)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.blablabla.android.core.test.TestDBActivity$3.onClick(TestDBActivity.java:169)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.view.View.performClick(View.java:2485)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.view.View$PerformClick.run(View.java:9080)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Handler.handleCallback(Handler.java:587)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Handler.dispatchMessage(Handler.java:92)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.os.Looper.loop(Looper.java:123)
08-13 13:17:16.480: D/SELECT on ui(1572): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-13 13:17:16.480: D/SELECT on ui(1572): at java.lang.reflect.Method.invokeNative(Native Method)
08-13 13:17:16.480: D/SELECT on ui(1572): at java.lang.reflect.Method.invoke(Method.java:507)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-13 13:17:16.480: D/SELECT on ui(1572): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-13 13:17:16.480: D/SELECT on ui(1572): at dalvik.system.NativeStart.main(Native Method)
/**
* Copies one CursorWindow into another. Previous data in destination
* CursorWindow is lost
*
* @param position
* Starting position to copy from the origin window
* @param numColumns
* Number of columns in the origin window
* @param origin
* CursorWindow to copy from
* @param destination
* CursorWindow to copy to
*/
public static void copyCursorWindow(int position, CursorWindow origin,
CursorWindow destination) {
// Column number
int numCols = getCursorWindowNumCols(origin);
// Clear destination
destination.clear();
destination.setNumColumns(numCols);
// Rows
int i = position;
while (i < origin.getNumRows() && destination.allocRow()) {
// Columns
for (int j = 0; j < numCols; j++) {
if (origin.isBlob(i, j)) {
byte[] cur = origin.getBlob(i, j);
destination.putBlob(cur, i, j);
} else if (origin.isFloat(i, j)) {
Float cur = origin.getFloat(i, j);
destination.putDouble(cur, i, j);
} else if (origin.isLong(i, j)) {
Long cur = origin.getLong(i, j);
destination.putLong(cur, i, j);
} else if (origin.isString(i, j)) {
String cur = origin.getString(i, j);
destination.putString(cur, i, j);
} else if (origin.isNull(i, j)) {
destination.putNull(i, j);
}
}
i++;
}
}
/**
* Copies one CursorWindow into another. Previous data in destination
* CursorWindow is lost
*
* @param position
* Starting position to copy from the origin window
* @param numColumns
* Number of columns in the origin window
* @param origin
* CursorWindow to copy from
* @param destination
* CursorWindow to copy to
*/
public static void copyCursorWindow(int position, CursorWindow origin,
CursorWindow destination) {
// Column number
int numCols = getCursorWindowNumCols(origin);
// Clear destination
destination.clear();
destination.setNumColumns(numCols);
// Rows
int i = position;
while (i < origin.getNumRows() && destination.allocRow()) {
// Columns
for (int j = 0; j < numCols; j++) {
if (origin.isNull(i, j)) {
destination.putNull(i, j);
} else if (origin.isFloat(i, j)) {
Float cur = origin.getFloat(i, j);
destination.putDouble(cur, i, j);
} else if (origin.isLong(i, j)) {
Long cur = origin.getLong(i, j);
destination.putLong(cur, i, j);
} else if (origin.isString(i, j)) {
String cur = origin.getString(i, j);
destination.putString(cur, i, j);
} else if (origin.isBlob(i, j)) {
byte[] cur = origin.getBlob(i, j);
destination.putBlob(cur, i, j);
}
}
i++;
}
}