IllegalArgumentException:无效列 - SEARCHVIEW
IllegalArgumentException: Invalid column - SEARCHVIEW
我想在使用 SearchView 时从我的数据库 table 获得建议。
我得到 IllegalArgumentException:无效的列(列的名称)
private static final HashMap<String, String> mColumnMap = buildColumnMap();
//Build a map for all columns that may be requested, which will be given to SQLiteQueryBuilder.
//This allow ContentProvider to request columns without the need to know real column names and
//create the alias itself
private static HashMap<String, String> buildColumnMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "rowid AS " +
CookingContract.FoodEntry.COLUMN_NAME);
map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "rowid AS " +
CookingContract.FoodEntry.COLUMN_DESCRIPTION);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + CookingContract.FoodEntry._ID);
return map;
}
//Return a Cursor over all words that match the given query
public Cursor getWordMatches(String query, String[] columns) {
String selection = CookingContract.FoodEntry.COLUMN_NAME + " LIKE ?";
String[] selectionArgs = new String[]{"%" + query + "%"};
return query(selection, selectionArgs, columns);
}
//The SQLiteBuilder provides a map for all possible columns requested to actual columns in the
//DB, creating a simple column alias mechanism by which the ContentProvider doesn't need to know
//the real column names
private Cursor query(String selection, String[] selectionArgs, String[] columns) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(CookingContract.FoodEntry.TABLE_NAME);
builder.setProjectionMap(mColumnMap);
Cursor cursor = builder.query(getReadableDatabase(),
columns, selection, selectionArgs, null, null, null);
if (cursor == null) {
return null;
} else if (!cursor.moveToFirst()) {
cursor.close();
return null;
}
return cursor;
}
}
这是我的 ContentProvider 的部分代码
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor retCursor;
switch (sUriMatcher.match(uri)) {
case SEARCH_SUGGEST:
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: +"uri");
}
return getSuggestions(selectionArgs[0]);
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
private Cursor getSuggestions(String query) {
query = query.toLowerCase();
String[] columns = new String[]{
CookingContract.FoodEntry._ID,
CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_DESCRIPTION,
};
return cookingDBHelper.getWordMatches(query, columns);
}
使用 setProjectionMap 我应该能够告诉 Android 我的列有什么名称并根据 SearchManager 约束使用它...
我做错了什么?
我认为你的投影图(mColumnMap)不正确,你的是这样的:
map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "rowid AS " +
CookingContract.FoodEntry.COLUMN_NAME);
map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "rowid AS " +
CookingContract.FoodEntry.COLUMN_DESCRIPTION);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
CookingContract.FoodEntry._ID);
这意味着您正在按以下方式映射列:
SUGGEST_COLUMN_NAME -> rowid AS COLUMN_NAME
SUGGEST_COLUMN_TEXT_2 -> rowid AS COLUMN_DESCRIPTION
SUGGEST_COLUMN_INTENT_DATA_ID -> rowid AS _ID
当查询构建器使用您的地图时,它会将列名称重命名为地图上作为值给出的名称,但根据您在地图上作为键提供的列,none您正在查询的当前列将被正确映射。
String[] columns = new String[]{
CookingContract.FoodEntry._ID,
CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_DESCRIPTION,
};
无法正确映射上面的列,因为其中 none 列作为投影图上的键存在。
可以在 this question.
上找到有关地图投影的一些示例及其有用的原因
考虑到custom suggestions上的指南,要返回的游标预计至少包含2列:_ID
和SUGGEST_COLUMN_TEXT_1
,因此我建议您更改您的地图到以下地图:
map.put(CookingContract.FoodEntry._ID,
CookingContract.FoodEntry._ID + " as " + SearchManager._ID);
map.put(CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_NAME + " as " + SearchManager.SUGGEST_COLUMN_TEXT_1);
map.put(CookingContract.FoodEntry.COLUMN_DESCRIPTION,
CookingContract.FoodEntry.COLUMN_DESCRIPTION + " as " + SearchManager.SUGGEST_COLUMN_TEXT_2);
使用此映射,您提供的列将按以下方式映射:
FoodEntry._ID -> _ID
FoodEntry.COLUMN_NAME -> FoodEntry.COLUMN_NAME as SUGGEST_COLUMN_TEXT_1
FoodEntry.COLUMN_DESCRIPTION -> FoodEntry.COLUMN_DESCRIPTION as SUGGEST_COLUMN_TEXT_2
请注意,我省略了 SUGGEST_COLUMN_INTENT_DATA_ID
列,因为我不知道您使用哪个列来查询数据库中的单个记录,它可能是 rowId
或 _ID
,可以根据需要调整投影图
另外请确保您正在配置 your manifest 中的 android:searchSuggestIntentAction
以正确处理操作。
希望这能让我们更清楚地思考异常。
我想在使用 SearchView 时从我的数据库 table 获得建议。
我得到 IllegalArgumentException:无效的列(列的名称)
private static final HashMap<String, String> mColumnMap = buildColumnMap();
//Build a map for all columns that may be requested, which will be given to SQLiteQueryBuilder.
//This allow ContentProvider to request columns without the need to know real column names and
//create the alias itself
private static HashMap<String, String> buildColumnMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "rowid AS " +
CookingContract.FoodEntry.COLUMN_NAME);
map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "rowid AS " +
CookingContract.FoodEntry.COLUMN_DESCRIPTION);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + CookingContract.FoodEntry._ID);
return map;
}
//Return a Cursor over all words that match the given query
public Cursor getWordMatches(String query, String[] columns) {
String selection = CookingContract.FoodEntry.COLUMN_NAME + " LIKE ?";
String[] selectionArgs = new String[]{"%" + query + "%"};
return query(selection, selectionArgs, columns);
}
//The SQLiteBuilder provides a map for all possible columns requested to actual columns in the
//DB, creating a simple column alias mechanism by which the ContentProvider doesn't need to know
//the real column names
private Cursor query(String selection, String[] selectionArgs, String[] columns) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(CookingContract.FoodEntry.TABLE_NAME);
builder.setProjectionMap(mColumnMap);
Cursor cursor = builder.query(getReadableDatabase(),
columns, selection, selectionArgs, null, null, null);
if (cursor == null) {
return null;
} else if (!cursor.moveToFirst()) {
cursor.close();
return null;
}
return cursor;
}
}
这是我的 ContentProvider 的部分代码
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor retCursor;
switch (sUriMatcher.match(uri)) {
case SEARCH_SUGGEST:
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: +"uri");
}
return getSuggestions(selectionArgs[0]);
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
private Cursor getSuggestions(String query) {
query = query.toLowerCase();
String[] columns = new String[]{
CookingContract.FoodEntry._ID,
CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_DESCRIPTION,
};
return cookingDBHelper.getWordMatches(query, columns);
}
使用 setProjectionMap 我应该能够告诉 Android 我的列有什么名称并根据 SearchManager 约束使用它... 我做错了什么?
我认为你的投影图(mColumnMap)不正确,你的是这样的:
map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "rowid AS " +
CookingContract.FoodEntry.COLUMN_NAME);
map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "rowid AS " +
CookingContract.FoodEntry.COLUMN_DESCRIPTION);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
CookingContract.FoodEntry._ID);
这意味着您正在按以下方式映射列:
SUGGEST_COLUMN_NAME -> rowid AS COLUMN_NAME
SUGGEST_COLUMN_TEXT_2 -> rowid AS COLUMN_DESCRIPTION
SUGGEST_COLUMN_INTENT_DATA_ID -> rowid AS _ID
当查询构建器使用您的地图时,它会将列名称重命名为地图上作为值给出的名称,但根据您在地图上作为键提供的列,none您正在查询的当前列将被正确映射。
String[] columns = new String[]{
CookingContract.FoodEntry._ID,
CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_DESCRIPTION,
};
无法正确映射上面的列,因为其中 none 列作为投影图上的键存在。
可以在 this question.
上找到有关地图投影的一些示例及其有用的原因考虑到custom suggestions上的指南,要返回的游标预计至少包含2列:_ID
和SUGGEST_COLUMN_TEXT_1
,因此我建议您更改您的地图到以下地图:
map.put(CookingContract.FoodEntry._ID,
CookingContract.FoodEntry._ID + " as " + SearchManager._ID);
map.put(CookingContract.FoodEntry.COLUMN_NAME,
CookingContract.FoodEntry.COLUMN_NAME + " as " + SearchManager.SUGGEST_COLUMN_TEXT_1);
map.put(CookingContract.FoodEntry.COLUMN_DESCRIPTION,
CookingContract.FoodEntry.COLUMN_DESCRIPTION + " as " + SearchManager.SUGGEST_COLUMN_TEXT_2);
使用此映射,您提供的列将按以下方式映射:
FoodEntry._ID -> _ID
FoodEntry.COLUMN_NAME -> FoodEntry.COLUMN_NAME as SUGGEST_COLUMN_TEXT_1
FoodEntry.COLUMN_DESCRIPTION -> FoodEntry.COLUMN_DESCRIPTION as SUGGEST_COLUMN_TEXT_2
请注意,我省略了 SUGGEST_COLUMN_INTENT_DATA_ID
列,因为我不知道您使用哪个列来查询数据库中的单个记录,它可能是 rowId
或 _ID
,可以根据需要调整投影图
另外请确保您正在配置 your manifest 中的 android:searchSuggestIntentAction
以正确处理操作。
希望这能让我们更清楚地思考异常。