Android對資料庫表有一個約定。就是每張表都應該至少有_id這列。ListView在使用CursorAdapter及其子類適配 cursor的時候,會預設的擷取 _id 這列的值,如果你建的表沒有 _id這列或者你的cursor中沒有_id這列(查詢時的projection中沒有_id)就報錯了。所以使用CursorAdapter及其子類的時候一定要使查詢時的projection包含_id。CursorAdapter中相關代碼如下:
1.注釋/** * Adapter that exposes data from a {@link android.database.Cursor Cursor} to a * {@link android.widget.ListView ListView} widget. The Cursor must include * a column named "_id" or this class will not work. */2.構造方法 public CursorAdapter(Context context, Cursor c) { init(context, c, true); }public CursorAdapter(Context context, Cursor c, boolean autoRequery) { init(context, c, autoRequery); } protected void init(Context context, Cursor c, boolean autoRequery) { boolean cursorPresent = c != null; mAutoRequery = autoRequery; mCursor = c; mDataValid = cursorPresent; mContext = context; mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1; mChangeObserver = new ChangeObserver(); if (cursorPresent) { c.registerContentObserver(mChangeObserver); c.registerDataSetObserver(mDataSetObserver); } }3.public void changeCursor(Cursor cursor) { if (cursor == mCursor) { return; } if (mCursor != null) { mCursor.unregisterContentObserver(mChangeObserver); mCursor.unregisterDataSetObserver(mDataSetObserver); mCursor.close(); } mCursor = cursor; if (cursor != null) { cursor.registerContentObserver(mChangeObserver); cursor.registerDataSetObserver(mDataSetObserver); mRowIDColumn = cursor.getColumnIndexOrThrow("_id"); mDataValid = true; // notify the observers about the new cursor notifyDataSetChanged(); } else { mRowIDColumn = -1; mDataValid = false; // notify the observers about the lack of a data set notifyDataSetInvalidated(); } }
其中cursor.getColumnIndexOrThrow(String columnName)如下:
/** * Returns the zero-based index for the given column name, or throws * {@link IllegalArgumentException} if the column doesn't exist. If you're not sure if * a column will exist or not use {@link #getColumnIndex(String)} and check for -1, which * is more efficient than catching the exceptions. * * @param columnName the name of the target column. * @return the zero-based column index for the given column name * @see #getColumnIndex(String) * @throws IllegalArgumentException if the column does not exist */ int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException;
所以只要Cursor不為空白,Cursor中必須存在_id列,CursorAdapter及其子類才能正常工作。