我开始研究机制 ContentProvider 当一个应用程序使用另一个应用程序的数据时,我决定编写一个简单的例子。我的目标是实现对数据库的更新,删除和插入请求。
我写了提供者和提供者的客户端,插入工作正常,但更新和删除请求适用于整个表,而不是特定记录。
我无法理解,我做错了什么?
这是我的提供者:
public class MyProvider extends ContentProvider {
final String LOG_TAG = "myLogs";
static final String DB_NAME = "mydb";
static final int DB_VERSION = 1;
static final String CONTACT_TABLE = "_id";
static final String CONTACT_id = "_id";
static final String CONTACT_NAME = "name";
static final String CONTACT_EMAIL = "email";
static final String DB_CREATE = "create table "+CONTACT_TABLE+"("+
CONTACT_id+" integer primary key autoincrement,"+
CONTACT_NAME+ " text,"+
CONTACT_EMAIL+" text);";
static final String AUTHORITY = "com.dandewine.user.contentprovider.AddressBook";
static final String CONTACT_PATH = "contacts";
public static final Uri CONTACT_CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/"+CONTACT_PATH);
static final String CONTACT_CONTENT_TYPE = "vnd.android.cursor.item/vnd."+AUTHORITY+"."+CONTACT_PATH;
static final int URI_CONTACT = 1;
static final int URI_CONTACT_ID = 2;
private static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, CONTACT_PATH, URI_CONTACT);
uriMatcher.addURI(AUTHORITY, CONTACT_PATH + "/#", URI_CONTACT);
}
DBHelper helper;
SQLiteDatabase db;
@Override
public boolean onCreate(){
Log.d(LOG_TAG,"onCreate");
helper = new DBHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.d(LOG_TAG,"query, "+uri.toString());
switch (uriMatcher.match(uri)){
case URI_CONTACT:
Log.d(LOG_TAG,"URI_CONTACTS");
if(TextUtils.isEmpty(sortOrder))
sortOrder=CONTACT_NAME+" ASC";
break;
case URI_CONTACT_ID:
String id = uri.getLastPathSegment();
Log.d(LOG_TAG,"URI_CONTACTS_ID,"+id);
if(TextUtils.isEmpty(selection))
selection=CONTACT_id+" = "+id;
else
selection=selection+" AND "+CONTACT_id+" = "+id;
break;
default:throw new IllegalArgumentException("Wrong URI: "+uri);
}
db = helper.getWritableDatabase();
Cursor cursor = db.query(CONTACT_TABLE,projection,selection,selectionArgs,null,null,sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(),CONTACT_CONTENT_URI);
return cursor;
}
@Override
public String getType(Uri uri) {
Log.d(LOG_TAG, "getType, " + uri.toString());
switch (uriMatcher.match(uri)) {
case URI_CONTACT:
return CONTACT_CONTENT_TYPE;
case URI_CONTACT_ID:
return CONTACT_CONTENT_TYPE;
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d(LOG_TAG,"insert, "+uri.toString());
if(uriMatcher.match(uri)!=URI_CONTACT)
throw new IllegalArgumentException("Wrong URI: "+uri);
db = helper.getWritableDatabase();
long rowID = db.insert(CONTACT_TABLE,null,values);
Uri resultURI = ContentUris.withAppendedId(CONTACT_CONTENT_URI,rowID);
getContext().getContentResolver().notifyChange(resultURI,null);
return resultURI;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d(LOG_TAG,"delete, "+uri.toString());
switch(uriMatcher.match(uri)){
case URI_CONTACT:
Log.d(LOG_TAG,"URI_CONTACT");
break;
case URI_CONTACT_ID:
String id = uri.getLastPathSegment();
Log.d(LOG_TAG,"URI_CONTACTS_ID, "+id);
if(TextUtils.isEmpty(selection))
selection=CONTACT_id+" = "+id;
else
selection = selection + " AND "+CONTACT_id+" = "+id;
break;
default:throw new IllegalArgumentException("Wrong URI: "+uri);
}
db = helper.getWritableDatabase();
int cnt = db.delete(CONTACT_TABLE,selection,selectionArgs);
getContext().getContentResolver().notifyChange(uri,null);
return cnt;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d(LOG_TAG, "update, " + uri.toString());
switch (uriMatcher.match(uri)) {
case URI_CONTACT:
Log.d(LOG_TAG, "URI_CONTACTS");
break;
case URI_CONTACT_ID:
String id = uri.getLastPathSegment();
Log.d(LOG_TAG, "URI_CONTACTS_ID, " + id);
if (TextUtils.isEmpty(selection)) {
selection = CONTACT_id + " = " + id;
} else {
selection = selection + " AND " + CONTACT_id + " = " + id;
}
break;
default:
throw new IllegalArgumentException("Wrong URI: " + uri);
}
db = helper.getWritableDatabase();
int cnt = db.update(CONTACT_TABLE, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return cnt;
}
private class DBHelper extends SQLiteOpenHelper{
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE);
ContentValues cv = new ContentValues();
for (int i = 0; i <=3 ; i++) {
cv.put(CONTACT_NAME,"name "+i);
cv.put(CONTACT_EMAIL,"email "+i);
db.insert(CONTACT_TABLE,null,cv);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
这是客户端应用:
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>,
View.OnClickListener {
final String LOG_TAG = "myLogs";
static final Uri CONTACT_URI = Uri.parse("content://com.dandewine.user.contentprovider.AddressBook/contacts");
SimpleCursorAdapter adapter;
final String CONTACT_NAME = "name";
final String CONTACT_EMAIL = "email";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String from[] = {"name","email"};
int to[] = {android.R.id.text1,android.R.id.text2};
adapter =new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,null,from,to,0);
ListView lvContact = (ListView)findViewById(R.id.lvContact);
lvContact.setAdapter(adapter);
getSupportLoaderManager().initLoader(0,null,this);
}
@Override
public void onClick(View v) {
Log.d(LOG_TAG,"onClick");
ContentValues cv = new ContentValues();
Uri uri;
int count;
switch (v.getId()){
case R.id.btnInsert:
cv.put(CONTACT_EMAIL,"email 4");
cv.put(CONTACT_NAME,"name 4");
uri = getContentResolver().insert(CONTACT_URI,cv);
Log.d(LOG_TAG,"insert, result Uri: "+uri.toString());
Toast.makeText(this,"Insert",Toast.LENGTH_SHORT).show();
break;
case R.id.btnDelete:
uri = ContentUris.withAppendedId(CONTACT_URI,3);
count = getContentResolver().delete(uri,null,null);
Log.d(LOG_TAG,"delete, count = "+count);
Toast.makeText(this,"Delete",Toast.LENGTH_SHORT).show();
break;
case R.id.btnUpdate:
cv.put(CONTACT_NAME,"name 5");
cv.put(CONTACT_EMAIL,"email 5");
uri = ContentUris.withAppendedId(CONTACT_URI,2);
count = getContentResolver().update(uri,cv,null,null);
Log.d(LOG_TAG,"update, count ="+count);
Toast.makeText(this,"Update",Toast.LENGTH_SHORT).show();
break;
case R.id.btnError:
Toast.makeText(this,"Error",Toast.LENGTH_SHORT).show();
uri = Uri.parse("content://com.dandewine.user.contentprovider.AddressBook/phones");
try{
Cursor cursor = getContentResolver().query(uri,null,null,null,null);
}catch (Exception ex){
Log.d(LOG_TAG, "Error: " + ex.getClass() + ", " + ex.getMessage());
}
break;
}
getSupportLoaderManager().getLoader(0).forceLoad();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new MyLoader(this,CONTACT_URI);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
private static class MyLoader extends android.support.v4.content.CursorLoader{
Uri uri;
public MyLoader(Context context,Uri uri) {
super(context,uri,null, null, null, null);
this.uri=uri;
}
@Override
public Cursor loadInBackground() {
return getContext().getContentResolver().query(uri,null,null,null,null);
}
}
}