我有一个 ListView ,其中包含一些保存在数据库中的元素,我使用自定义内容提供程序访问它们。
在我的主要 Activity 中,我实现了 ResourceCursorAdapter。
当我长按列表中的一个元素时,我会看到一个上下文菜单,其中包含编辑更新选项。
编辑选项使用一些编辑文本启动其他 Activity ,我应该能够在其中更新所选项目的值(我也使用此 Activity 来创建新项目,我做对了)。
我遇到的问题是我没有更新或删除项目,所以我认为我没有管理正确的 ID 来访问数据库。这是我的代码:
自定义内容提供者 - 更新和删除方法
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;
database = mDbHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
String id = uri.getPathSegments().get(1);
count = database.update(TravelsDatabaseHelper.TABLE_NAME, values, Travels._ID +
" = " + id + (!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
database = mDbHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
String id = uri.getPathSegments().get(1);
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, Travels._ID + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
主要 Activity - 更新和删除方法
public void updateTravel(String city, String country, int year, String note, String id){
ContentValues updateValues = new ContentValues();
updateValues.put(Travels.CITY, city);
updateValues.put(Travels.COUNTRY, country);
updateValues.put(Travels.YEAR, year);
updateValues.put(Travels.NOTE, note);
getContentResolver().update(TravelsProvider.CONTENT_URI, updateValues, Travels._ID+"="+id, null);
}
private void deleteTravel(String id){
/**Accede a la funcion delete() del Content Provider*/
getContentResolver().delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null);
}
主要 Activity - 我调用删除和更新方法的上下文菜单
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo menu_info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int itemPos = menu_info.position;
Cursor cursor = mAdapter.getCursor();
cursor.moveToPosition(itemPos);
switch (item.getItemId()) {
case R.id.edit_travel:
Intent intent = new Intent(this, EditTravelActivity.class);
intent.putExtra(TravelActivity.EXTRA_ID, cursor.getString(cursor.getColumnIndex(Travels._ID)));
startActivityForResult(intent, REQUEST_CODE_UPDATE_TRAVEL);
return true;
case R.id.delete_travel:
String ids = cursor.getString(cursor.getColumnIndex(Travels._ID));
deleteTravel(ids);
return true;
default:
return super.onContextItemSelected(item);
}
}
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
//...
case REQUEST_CODE_UPDATE_TRAVEL:
String ucity = data.getExtras().getString(TravelActivity.EXTRA_CITY);
String ucountry = data.getExtras().getString(TravelActivity.EXTRA_COUNTRY);
int uyear = data.getExtras().getInt(TravelActivity.EXTRA_YEAR);
String unote = data.getExtras().getString(TravelActivity.EXTRA_NOTE);
String uid = data.getExtras().getString(TravelActivity.EXTRA_ID);
updateTravel(ucity, ucountry, uyear, unote, uid);
break;
}
}
}
更新 - 根据 NigelK 的回答
这是我的“UriMatcher”和其他需要注意的相关定义:
private static final String AUTHORITY = "com.example.travellist";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/travels");
private static final int URI_TRAVELS = 1;
private static final int URI_TRAVEL_ITEM = 2;
private static final UriMatcher mUriMatcher;
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(AUTHORITY, "travels", URI_TRAVELS);
mUriMatcher.addURI(AUTHORITY, "travels/#", URI_TRAVEL_ITEM);
}
我不需要以摊位的方式去做,我正在学习这个,所以只要以最好的方式去做就足以让我学习。
根据您的回答,我尝试了两种方式:
private void deleteTravel(long id){
/*METHOD 1*/
getContentResolver().delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null);
/*METHOD 2*/
Uri uri = ContentUris.withAppendedId(TravelsProvider.CONTENT_URI, id);
getContentResolver().delete(uri, null, null);
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
//...
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
/*METHOD 1*/
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, selection, selectionArgs);
break;
/*METHOD 2*/
String rowId = uri.getPathSegments().get(1);
selection = Travels._ID +" = "+ rowId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, selection, selectionArgs);
break;
//...
}
在第一种方式中,它会在不删除项目的情况下继续。在第二种方式中,在 String rowId = uri.getPathSegments().get(1); 行中抛出此错误:Unreachable code!
最佳答案
大多数内容提供程序都包含一个快捷方式 URI 模式,允许您通过将行 ID 附加到内容 URI 来寻址特定行。在执行以下操作的地方,您提供了完全有效的选择“WHERE _id = id”:
.delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null);
上面的 uri 类似于:content://com.package.provider/content
将操作仅应用于附加到 uri 的 id 的快捷方式具有以下形式:
uri = ContentUris.withAppendedId(TravelsProvider.CONTENT_URI, id);
.delete(uri, null, null);
上面的 uri 现在类似于:content://com.package.provider/content/1234
您遇到的问题是,在您的 delete() 和 update() 方法中,您正在尝试处理第二种形式,而不是第一种形式(这是您在调用中使用的 URI 形式)。扩展您的 uriMatcher 以区分它们,例如:
uriMatcher.addURI("your.package.provider", "content", URI_TRAVEL_ITEM);
uriMatcher.addURI("your.package.provider", "content/#", URI_TRAVEL_ITEM_ID);
在 delete() 中,和 update() 类似:
switch (match){
case URI_TRAVELS:
//nada
break;
case URI_TRAVEL_ITEM:
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, selection, selectionArgs);
break;
case URI_TRAVEL_ITEM_ID:
String rowID = uri.getPathSegments().get(1);
selection = Travels._ID + "=" + rowID
+ (!TextUtils.isEmpty(selection) ?
" AND (" + selection + ')' : "");
count = database.delete(TravelsDatabaseHelper.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
因此,如果 URI 没有附加 id(它匹配 URI_TRAVEL_ITEM),它是基于选择和参数的直接删除。 如果 URI 附加了一个 id(它匹配 URI_TRAVEL_ITEM_ID),使用 getPathSegments().get(1) 从 URI 中获取 id,并使用该值来扩充之前传入的选择(因此它仅适用于该行)进行删除。
然后您已经涵盖了两种类型的 URI,并且您的其余代码应该(我希望)工作。
关于android - 使用 Content Provider 更新数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21133757/