2014-01-15 49 views
1

我有一些保存在數據庫中的元素的列表視圖,我使用自定義內容提供程序訪問它們。使用內容提供程序更新數據庫

在我的主要活動中,我實現了一個ResourceCursorAdapter。

當我長時間點擊列表中的一個元素時,我得到一個上下文菜單,其中有編輯更新選項。

編輯選項啓動其他活動與一些edittexts,我應該能夠更新選定的項目的值(我也使用這個活動來創建一個新的項目,我這樣做的權利)。

我得到的問題是我沒有得到更新或刪除的項目,所以我認爲我沒有管理正確的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; 
} 

主要活動 - 更新和刪除方法

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); 
} 

主要活動 - 上下文菜單在哪裏呼叫刪除和更新方法

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」和其他相關定義的照顧:

​​

我並不需要做的是在展臺的方式,我正在學習這一點,所以只要以最好的方式來做就足以讓我學習。

根據你的答案,我tryed做了2種方式:

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);拋出此錯誤:無法訪問的代碼!

回答

2

大多數內容提供者都包含一個快捷URI模式,它允許您通過向內容URI附加行ID來尋址特定行。當你做到以下幾點,您提供的選擇「WHERE _id = ID」,這是完全正確的:

.delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null); 

的URI上面會是這樣的:內容://com.package.provider/content

的短切,適用的動作,只是追加到URI的ID,是下面的形式:

uri = ContentUris.withAppendedId(TravelsProvider.CONTENT_URI, id); 
.delete(uri, null, null); 

的URI上面現在是這樣的:內容://com.package。提供者/內容/ 1234

你的問題是,在你的delete()和update()方法中,你試圖處理第二種形式,而不是第一種(這是你使用的URI形式電話)。展開你的uriMatcher分辨出來,是這樣的:

uriMatcher.addURI("your.package.provider", "content", URI_TRAVEL_ITEM); 
uriMatcher.addURI("your.package.provider", "content/#", URI_TRAVEL_ITEM_ID); 

在刪除(),同樣的更新():

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); 
} 

那麼,沒有ID附加到URI(它匹配URI_TRAVEL_ITEM),它是基於選擇和參數的直接刪除。 如果有一個id附加到URI(它與URI_TRAVEL_ITEM_ID匹配),使用getPathSegments()。get(1)從URI獲取id並使用該值來擴充傳入的選擇(所以它只適用於該行)在做刪除之前。

然後,你已經覆蓋了這兩種類型的URI,其餘的代碼應該(我希望)工作。

+0

我已根據您的答案更新了我的帖子。仍然沒有工作,所以也許我誤解了一些東西。請看看 – masmic

+0

也許,問題出在mainActivity中,我使用'String ids = cursor.getString(cursor.getColumnIndex(Travels._ID))獲取物品ID;'也許,這不是獲取物品的ID? – masmic

+0

無法訪問的代碼是因爲您錯過了「案例URI_TRAVEL_ITEM_ID:」 - 請參閱我的答案,瞭解它的具體位置。仍然看着其餘的...... – NigelK

相關問題