API Level <11的Cursor.getType()

我正在查询CallLog内容提供者,需要检测列types。

在Honeycomb和更高版本(API Level 11+)中,可以通过调用Cursor.getType(int columnIndex)方法获得列首选数据types,该方法返回以下types之一:

  • FIELD_TYPE_NULL(0)
  • FIELD_TYPE_INTEGER(1)
  • FIELD_TYPE_FLOAT(2)
  • FIELD_TYPE_STRING(3)
  • FIELD_TYPE_BLOB(4)

我如何在Honeycomb <11器件上完成这项工作?

我已经尝试了以下内容:

 for ( int i = 0; i < cursor.getColumnCount(); i++ ) { int columnType = -1; try { cursor.getInt( i ); columnType = Cursor.FIELD_TYPE_INTEGER; } catch ( Exception ignore ) { try { cursor.getString( i ); columnType = Cursor.FIELD_TYPE_STRING; } catch ( Exception ignore1 ) { try { cursor.getFloat( i ); columnType = Cursor.FIELD_TYPE_FLOAT; } catch ( Exception ignore2 ) { try { cursor.getBlob( i ); columnType = Cursor.FIELD_TYPE_BLOB; } catch ( Exception ignore3 ) { columnType = Cursor.FIELD_TYPE_NULL; } } } } } 

但是,不会抛出exception。 数据总是以您正在检查的第一种types(在本例中为getInt())进行铸造。 这意味着,如果列types是整数 ,则得到正确的值,但对于所有其他types,则为0

为什么我不查看文档来检查存储的types? 这些列根据设备制造商的不同而不同,并不是所有文档都有logging,请参阅此问题: 如何处理ContentProvider中与制造商相关的差异?

有任何想法吗?

Solutions Collecting From Web of "API Level <11的Cursor.getType()"

游标位于有效行时,可以使用此代码:

 CursorWrapper cw = (CursorWrapper)cursor; Class<?> cursorWrapper = CursorWrapper.class; Field mCursor = cursorWrapper.getDeclaredField("mCursor"); mCursor.setAccessible(true); AbstractWindowedCursor abstractWindowedCursor = (AbstractWindowedCursor)mCursor.get(cw); CursorWindow cursorWindow = abstractWindowedCursor.getWindow(); int pos = abstractWindowedCursor.getPosition(); for ( int i = 0; i < cursor.getColumnCount(); i++ ) { String type = null; if (cursorWindow.isNull(pos, i)) { type = "Cursor.FIELD_TYPE_NULL"; } else if (cursorWindow.isLong(pos, i)) { type = "Cursor.FIELD_TYPE_INTEGER"; } else if (cursorWindow.isFloat(pos, i)) { type = "Cursor.FIELD_TYPE_FLOAT"; } else if (cursorWindow.isString(pos, i)) { type = "Cursor.FIELD_TYPE_STRING"; } else if (cursorWindow.isBlob(pos, i)) { type = "Cursor.FIELD_TYPE_BLOB"; } } 

请注意,Cursor.FIELD_TYPE_ *常数值是从HONEYCOMB开始定义的。

扩展Juan的答案,这里是我的API 11方法Cursor.getType(int i)的替代 – 对于由SQL查询返回的游标

 public class DbCompat { protected static final int FIELD_TYPE_BLOB = 4; protected static final int FIELD_TYPE_FLOAT = 2; protected static final int FIELD_TYPE_INTEGER = 1; protected static final int FIELD_TYPE_NULL = 0; protected static final int FIELD_TYPE_STRING = 3; static int getType(Cursor cursor, int i) throws Exception { SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor; CursorWindow cursorWindow = sqLiteCursor.getWindow(); int pos = cursor.getPosition(); int type = -1; if (cursorWindow.isNull(pos, i)) { type = FIELD_TYPE_NULL; } else if (cursorWindow.isLong(pos, i)) { type = FIELD_TYPE_INTEGER; } else if (cursorWindow.isFloat(pos, i)) { type = FIELD_TYPE_FLOAT; } else if (cursorWindow.isString(pos, i)) { type = FIELD_TYPE_STRING; } else if (cursorWindow.isBlob(pos, i)) { type = FIELD_TYPE_BLOB; } return type; } } 

要点: https : //gist.github.com/kassim/c340cbfc5243db3a4826

有一些可能的工作: http : //developer.android.com/reference/android/database/DatabaseUtils.html cursorRowToContentValues

将复制ContentValues对象中的行。 然后,你可以调用ContentValues.get(),它给你一个对象。 然后你可以看看这个对象的Class。

编辑

根据DatabaseUtils的源代码,对象是blob或者Strings。

编辑2

但是,如果你的游标是一个WindowedCursor,它有方法来知道对象types。 (isBlob,isString,isLong …)

我过去也面临同样的问题。 我用一个很好的解决scheme来解决它。 匹配您的需求。 在我的情况下,我有很多不同的对象,这些对象都被同步到云中的服务器。 他们都有共同的属性,所以他们都从一个共同的BaseObjectinheritance。 这个对象有一个方法,它将一个游标作为参数,并返回一个相同types的新对象,这样每个从它inheritance的对象都会覆盖这个方法的扩展属性。

*请注意,这种方法不需要inheritance对象。 这只是一个更聪明的做法。 只要你在所有的对象中都有相同的方法,你需要采取表单数据库,这将工作,你将能够看到最后。

让我来说明一下:

我们的baseObject。

 public class BaseObject{ protected int number; protected String text; public <T extends BaseObject> T setObject(Cursor c) { number = c.getInt(cur.getColumnIndexOrThrow(COLUMN_NAME_FOR_NUMBER)); text = c.getString(cur.getColumnIndexOrThrow(COLUMN_NAME_FOR_TEXT)); return (T) this; } } 

一个从第一个inheritance的新对象。

 public class Contact extends BaseObject{ private String name; @Override public <T extends BaseObject> T setObject(Cursor c) { super.setObject(c); name = c.getString(cur.getColumnIndexOrThrow(COLUMN_NAME_FOR_NAME)); return (T) this; } } 

最后,在数据库中,通过调用通用方法“getAllObjects”并传递要查询的类types以及查询的其他参数,就可以轻松地询问所需的数据:

 public synchronized <T extends BaseObject> ArrayList<T> getObjectsForClass(final Class<T> classType, String selection, String[] selectionArgs, String sort, String limit) { ArrayList<T> objects = null; if (db == null || !db.isOpen()) { db = getWritableDatabase(); } objects = new ArrayList<T>(); Cursor c = null; T object; try { object = classType.newInstance(); String table = object.getTable(); StringBuilder tableSb = new StringBuilder(); tableSb.append(table).append(" INNER JOIN ").append(Constants.DB_BASE_OBJECT_TABLE) .append(" ON ").append(table).append(".").append(BaseObject.DB_OBJECT_ID_KEY).append(" = ") .append(Constants.DB_BASE_OBJECT_TABLE).append(".") .append(BaseObject.DB_ID_KEY); c = db.query(tableSb.toString(), null, selection, selectionArgs, null, null, sort, limit); if (c.getCount() > 0) { c.moveToFirst(); while (!c.isAfterLast()) { object = classType.newInstance(); object.setObject(c); objects.add(object); c.moveToNext(); } } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } c.close(); return objects; } 

你去了。 一种通用的方法,可以从数据库获取任何对象,并在运行时成功将其转换为对象或对象数组。

笔记:

  • 每个对象都应该有一个方法getTable(),以便能够查询正确的表
  • 在这种方法中,您也可以看到OODB连接。 您可以使用相同的方法,只要查询所有项目(SELECT * FROM …)

希望能帮助到你。 回答问题或怀疑。