当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。ContentResolver类提供了与ContentProvider类相同签名的四个方法:
public Uri insert(Uri uri, ContentValues values)
该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs)
该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
该方法用于从ContentProvider中获取数据。
这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,假设给定的是:Uri.parse(“content://cn.itcast.providers.personprovider/person/10”),那么将会对主机名为cn.itcast.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。
这里使用 3个项目程序,sqlLite (数据库实际操作的项目,内容提供者)、sqlA (数据调用方)、sqlB (监听方);
sqlLite:
1、需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider,ContentProvider采用了authorities(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:
<provider android:name=".PersonProvider" android:authorities="emal30.no7.SqlLite.PersonProvider" />
2、基于 ContentProvider 类派生出 PersonProvider 类用于向外部共享出他的 insert(除了增加插入记录还提供了,数据修改通知)、delete、update、query、getType方法,用于修改数据等操作。
已修改数据库表为例:
public class PersonProvider extends ContentProvider { DBOpenHelpter dbHelp;//执行类 private static final UriMatcher MATCHER=new UriMatcher(-1);//数据不匹配时返回-1 static{ // emal30.no7.SqlLite.PersonProvider/person MATCHER.addURI("emal30.no7.SqlLite.PersonProvider", "person", 1);//无参数地址是返回1 // emal30.no7.SqlLite.PersonProvider/person/20 MATCHER.addURI("emal30.no7.SqlLite.PersonProvider", "person/#", 2);//有参数地址是返回2 } @Override public int delete(Uri arg0, String arg1, String[] arg2) { // TODO Auto-generated method stub SQLiteDatabase db=dbHelp.getWritableDatabase(); int num=0; switch(MATCHER.match(arg0)){ case 1: num=db.delete("person", null, arg2); break; case 2: long rowid=ContentUris.parseId(arg0); String where="personid="+rowid; if(arg1!=null && !"".equals(arg1.trim())) { where+=" and "+arg1; } num=db.delete("person", where, arg2); break; default: throw new IllegalArgumentException("this is Unknown Uri:"+arg0); } return num; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub switch(MATCHER.match(uri)){ case 1: return "无参数短路径"; case 2: return "有参数长路径"; default: throw new IllegalArgumentException("this is Unknown Uri:"+uri); } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub SQLiteDatabase db=dbHelp.getWritableDatabase(); switch(MATCHER.match(uri)){ case 1: long rowid=db.insert("person", "name", values); //返回主键 Uri inserUri=ContentUris.withAppendedId(uri, rowid); this.getContext().getContentResolver().notifyChange(uri, null); //发送数据变化通知 return inserUri; default: throw new IllegalArgumentException("this is Unknown Uri:"+uri); } } @Override public boolean onCreate() { // TODO Auto-generated method stub dbHelp=new DBOpenHelpter(this.getContext()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub SQLiteDatabase db=dbHelp.getWritableDatabase(); int num=0; Cursor cursor; long rowid; switch(MATCHER.match(uri)){ case 1: cursor=db.query("person", projection, selection, selectionArgs, null, null, sortOrder); break; case 2: rowid=ContentUris.parseId(uri); String where="personid="+rowid; if(selection!=null && !"".equals(selection.trim())) { where+=" and "+selection; } cursor=db.query("person", projection, where, selectionArgs, null, null, sortOrder); break; default: throw new IllegalArgumentException("this is Unknown Uri:" + uri); } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub SQLiteDatabase db=dbHelp.getWritableDatabase(); int num=0; long rowid; switch(MATCHER.match(uri)){ case 1: num=db.update("person", values, selection, selectionArgs); break; case 2: rowid=ContentUris.parseId(uri); String where="personid="+rowid; if(selection!=null && !"".equals(selection.trim())) { where+=" and "+selection; } num=db.update("person", values, where, selectionArgs); break; default: throw new IllegalArgumentException("this is Unknown Uri:" + uri); } return num; } }
sqlA:使用ContentResolver操作ContentProvider中的数据,实现从外部访问sqlLite项目提供的内容提供者。OnC(View v)为入口函数点击直接关联就行,这里实现了4种调用;
public void OnC(View v){ //Toast.makeText(this.getApplicationContext(), "内容提示", 1); try { testInsert(); //testDel(); //testUpdate(); //testquest(); Log.i("Tag", "OK"); } catch (Exception e) { // TODO Auto-generated catch block Log.i("Tag", "NO"); e.printStackTrace(); } } public void testInsert() throws Exception{ Uri uri=Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person"); ContentResolver resolver=this.getContentResolver(); ContentValues values=new ContentValues(); values.put("name", "laoli"); values.put("phone", "138035201254"); resolver.insert(uri, values); } public void testDel(){ Uri uri=Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person/2"); ContentResolver resolver=this.getContentResolver(); resolver.delete(uri, null, null); } public void testUpdate(){ Uri uri=Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person/3"); ContentResolver resolver=this.getContentResolver(); ContentValues values=new ContentValues(); values.put("name", "dd"); values.put("phone", "dd"); resolver.update(uri, values, null, null); } public void testquest() { Uri uri=Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person"); ContentResolver resolver=this.getContentResolver(); Cursor con=resolver.query(uri,null,null,null,"personid asc"); while(con.moveToNext()) { String name=con.getString(con.getColumnIndex("name")); String phone=con.getString(con.getColumnIndex("phone")); Log.i("Tag", name + "----" + phone); } con.close(); }
sqlB:当执行sqlA中的 testInsert() 方法是 会触发 sqlLite中 this.getContext().getContentResolver().notifyChange(uri, null); //发送数据变化通知 ,从而被sqlB捕获
如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:
启动 sqlB 后点击按钮 会执行 onCk(View v) 执行注册监听
public void onCk(View v) { getContentResolver().registerContentObserver(Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person"), true, new PersonObserver(new Handler())); Log.i("Tag", "挂在成功");//注册监听成功 } public class PersonObserver extends ContentObserver{ public PersonObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub Uri uri=Uri.parse("content://emal30.no7.SqlLite.PersonProvider/person"); ContentResolver resolver=getContentResolver(); Cursor con=resolver.query(uri,null,null,null,"personid desc limit 1"); if(con.moveToFirst()) { Log.i("Tag", con.getString(0)+"---"+con.getString(1)); } } }
执行顺序: sqlLite (数据库实际操作的项目,内容提供者)、sqlB (监听方)、sqlA (数据调用方);
执行日志: