AndroID 中自定义ContentProvIDer与ContentObserver的使用简单实例
示例说明:
该示例中一共包含两个工程。其中一个工程完成了自定义ContentProvIDer,另外一个工程用于测试该自定义ContentProvIDer且在该工程中使用了ContentObserver监听自定义ContentProvIDer的数据变化
以下代码为工程TestContentProvIDer
ContentProvIDerTest如下:
package cn.testcontentprovIDer; import androID.content.ContentProvIDer; import androID.content.ContentUris; import androID.content.ContentValues; import androID.content.UriMatcher; import androID.database.Cursor; import androID.database.sqlite.sqliteDatabase; import androID.net.Uri; /** * Demo描述: * 自定义ContentProvIDer的实现 * ContentProvIDer主要用于在不同的应用程序之间共享数据,这也是官方推荐的方式. * * 注意事项: * 1 在AndroIDManifest.xml中注册ContentProvIDer时的属性 * androID:exported="true"表示允许其他应用访问. * 2 注意*和#这两个符号在Uri中的作用 * 其中*表示匹配任意长度的字符 * 其中#表示匹配任意长度的数据 * 所以: * 一个能匹配所有表的Uri可以写成: * content://cn.bs.testcontentprovIDer/* * 一个能匹配person表中任意一行的Uri可以写成: * content://cn.bs.testcontentprovIDer/person/# * */ public class ContentProvIDerTest extends ContentProvIDer { private sqliteDatabaSEOpenHelper msqliteDatabaSEOpenHelper; private final static String AUTHORITY="cn.bs.testcontentprovIDer"; private static UriMatcher mUriMatcher; private static final int PERSON_DIR = 0; private static final int PERSON = 1; /** * 利用静态代码块初始化UriMatcher * 在UriMatcher中包含了多个Uri,每个Uri代表一种 *** 作 * 当调用UriMatcher.match(Uri uri)方法时就会返回该uri对应的code; * 比如此处的PERSONS和PERSON */ static { mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // 该URI表示返回所有的person,其中PERSONS为该特定Uri的标识码 mUriMatcher.addURI(AUTHORITY,"person",PERSON_DIR); // 该URI表示返回某一个person,其中PERSON为该特定Uri的标识码 mUriMatcher.addURI(AUTHORITY,"person/#",PERSON); } /** * 在自定义ContentProvIDer中必须覆写getType(Uri uri)方法. * 该方法用于获取Uri对象所对应的MIME类型. * * 一个Uri对应的MIME字符串遵守以下三点: * 1 必须以vnd开头 * 2 如果该Uri对应的数据可能包含多条记录,那么返回字符串应该以"vnd.androID.cursor.dir/"开头 * 3 如果该Uri对应的数据只包含一条记录,那么返回字符串应该以"vnd.androID.cursor.item/"开头 */ @OverrIDe public String getType(Uri uri) { switch (mUriMatcher.match(uri)) { case PERSON_DIR: return "vnd.androID.cursor.dir/"+AUTHORITY+".persons"; case PERSON: return "vnd.androID.cursor.item/"+AUTHORITY+".person"; default: throw new IllegalArgumentException("unkNown uri"+uri.toString()); } } @OverrIDe public boolean onCreate() { msqliteDatabaSEOpenHelper=new sqliteDatabaSEOpenHelper(getContext()); return true; } /** * 插入 *** 作: * 插入 *** 作只有一种可能:向一张表中插入 * 返回结果为新增记录对应的Uri * 方法db.insert()返回结果为新增记录对应的主键值 */ @OverrIDe public Uri insert(Uri uri,ContentValues values) { sqliteDatabase db = msqliteDatabaSEOpenHelper.getWritableDatabase(); switch (mUriMatcher.match(uri)) { case PERSON_DIR: long newID = db.insert("person","name,phone,salary",values); //向外界通知该ContentProvIDer里的数据发生了变化,以便ContentObserver作出相应 getContext().getContentResolver().notifyChange(uri,null); return ContentUris.withAppendedID(uri,newID); default: throw new IllegalArgumentException("unkNown uri" + uri.toString()); } } /** * 更新 *** 作: * 更新 *** 作有两种可能:更新一张表或者更新某条数据 * 在更新某条数据时原理类似于查询某条数据,见下. */ @OverrIDe public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs) { sqliteDatabase db = msqliteDatabaSEOpenHelper.getWritableDatabase(); int updatednum = 0; switch (mUriMatcher.match(uri)) { // 更新表 case PERSON_DIR: updatednum = db.update("person",values,selection,selectionArgs); break; // 按照ID更新某条数据 case PERSON: long ID = ContentUris.parseID(uri); String where = "personID=" + ID; if (selection != null && !"".equals(selection.trim())) { where = selection + " and " + where; } updatednum = db.update("person",where,selectionArgs); break; default: throw new IllegalArgumentException("unkNown uri" + uri.toString()); } //向外界通知该ContentProvIDer里的数据发生了变化,以便ContentObserver作出相应 getContext().getContentResolver().notifyChange(uri,null); return updatednum; } /** * 删除 *** 作: * 删除 *** 作有两种可能:删除一张表或者删除某条数据 * 在删除某条数据时原理类似于查询某条数据,见下. */ @OverrIDe public int delete(Uri uri,String[] selectionArgs) { sqliteDatabase db = msqliteDatabaSEOpenHelper.getWritableDatabase(); int deletednum = 0; switch (mUriMatcher.match(uri)) { // 删除表 case PERSON_DIR: deletednum = db.delete("person",selectionArgs); break; // 按照ID删除某条数据 case PERSON: long ID = ContentUris.parseID(uri); String where = "personID=" + ID; if (selection != null && !"".equals(selection.trim())) { where = selection + " and " + where; } deletednum = db.delete("person",null); return deletednum; } /** * 查询 *** 作: * 查询 *** 作有两种可能:查询一张表或者查询某条数据 * * 注意事项: * 在查询某条数据时要注意--因为此处是按照personID来查询 * 某条数据,但是同时可能还有其他限制.例如: * 要求personID为2且name为xiaoming1 * 所以在查询时分为两步: * 第一步: * 解析出personID放入where查询条件 * 第二步: * 判断是否有其他限制(如name),若有则将其组拼到where查询条件. * * 详细代码见下. */ @OverrIDe public Cursor query(Uri uri,String[] projection,String[] selectionArgs,String sortOrder) { sqliteDatabase db = msqliteDatabaSEOpenHelper.getWritableDatabase(); Cursor cursor =null; switch (mUriMatcher.match(uri)) { // 查询表 case PERSON_DIR: cursor = db.query("person",projection,selectionArgs,null,sortOrder); break; // 按照ID查询某条数据 case PERSON: // 第一步: long ID = ContentUris.parseID(uri); String where = "personID=" + ID; // 第二步: if (selection != null && !"".equals(selection.trim())) { where = selection + " and " + where; } cursor = db.query("person",sortOrder); break; default: throw new IllegalArgumentException("unkNown uri" + uri.toString()); } return cursor; } }
sqliteDatabaSEOpenHelper如下:
package cn.testcontentprovIDer; import androID.content.Context; import androID.database.sqlite.sqliteDatabase; import androID.database.sqlite.sqliteOpenHelper; public class sqliteDatabaSEOpenHelper extends sqliteOpenHelper { public sqliteDatabaSEOpenHelper(Context context) { super(context,"contentprovIDertest.db",1); } @OverrIDe public voID onCreate(sqliteDatabase db) { db.execsql("create table person(personID integer primary key autoincrement,name varchar(20),phone varchar(12),salary Integer(12))"); } //当数据库版本号发生变化时调用该方法 @OverrIDe public voID onUpgrade(sqliteDatabase db,int arg1,int arg2) { //db.execsql("ALTER table person ADD phone varchar(12) NulL"); //db.execsql("ALTER table person ADD salary Integer NulL"); } } MainActivity如下:[java] vIEw plain copypackage cn.testcontentprovIDer; import androID.app.Activity; import androID.os.Bundle; public class MainActivity extends Activity { @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.main); } }
AndroIDManifest.xml如下:
<?xml version="1.0" enCoding="utf-8"?> <manifest xmlns:androID="http://schemas.androID.com/apk/res/androID" package="cn.testcontentprovIDer" androID:versionCode="1" androID:versionname="1.0" > <uses-sdk androID:minSdkVersion="8" androID:targetSdkVersion="8" /> <uses-permission androID:name="androID.permission.INTERNET" /> <uses-permission androID:name="androID.permission.ACCESS_NETWORK_STATE" /> <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission androID:name="androID.permission.MOUNT_UNMOUNT_fileSYstemS" /> <application androID:allowBackup="true" androID:icon="@drawable/ic_launcher" androID:label="@string/app_name" androID:theme="@style/Apptheme" > <activity androID:name="cn.testcontentprovIDer.MainActivity" androID:label="@string/app_name" > <intent-filter> <action androID:name="androID.intent.action.MAIN" /> <category androID:name="androID.intent.category.LAUNCHER" /> </intent-filter> </activity> <provIDer androID:name="cn.testcontentprovIDer.ContentProvIDerTest" androID:authoritIEs="cn.bs.testcontentprovIDer" androID:exported="true" /> </application> </manifest>
main.xml如下:
<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" > <button androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="该应用包含一个自定义的ContentProvIDer" androID:textSize="15sp" androID:layout_centerInParent="true" /> </relativeLayout>
以下代码为工程TestBaIDu
MainActivity如下:
package cn.testbaIDu; import androID.net.Uri; import androID.os.Bundle; import androID.os.Handler; import androID.vIEw.VIEw; import androID.vIEw.VIEw.OnClickListener; import androID.Widget.button; import androID.app.Activity; import androID.content.ContentResolver; import androID.content.ContentValues; import androID.database.ContentObserver; import androID.database.Cursor; /** * Demo描述: * 应用A(TestBaIDu)调用另外一个应用(TestContentProvIDer)中的自定义ContentProvIDer,即: * 1 自定义ContentProvIDer的使用 * 2 其它应用调用该ContentProvIDer * 3 ContentObserver的使用 * * 备注说明: * 1 该例子在以前版本的基础上整理了代码 * 2 该例子在以前版本的基础上融合了ContentObserver的使用 * 利用ContentObserver随时监听ContentProvIDer的数据变化. * 为实现该功能需要在自定义的ContentProvIDer的insert(),update(),delete() * 方法中调用getContext().getContentResolver().notifyChange(uri,null); * 向外界通知该ContentProvIDer里的数据发生了变化,以便ContentObserver作出相应 * * 测试方法: * 1 依次测试ContentProvIDer的增查删改(注意该顺序)!! * 2 其它应用查询该ContentProvIDer的数据 * */ public class MainActivity extends Activity { private button mAddbutton; private button mDeletebutton; private button mUpdatebutton; private button mquerybutton; private button mTypebutton; private long lastTime=0; private ContentResolver mContentResolver; private ContentObserverSubClass mContentObserverSubClass; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.main); init(); initContentObserver(); } private voID init() { mContentResolver=this.getContentResolver(); mAddbutton=(button) findVIEwByID(R.ID.addbutton); mAddbutton.setonClickListener(new ClickListenerImpl()); mDeletebutton=(button) findVIEwByID(R.ID.deletebutton); mDeletebutton.setonClickListener(new ClickListenerImpl()); mUpdatebutton=(button) findVIEwByID(R.ID.updatebutton); mUpdatebutton.setonClickListener(new ClickListenerImpl()); mquerybutton=(button) findVIEwByID(R.ID.querybutton); mquerybutton.setonClickListener(new ClickListenerImpl()); mTypebutton=(button) findVIEwByID(R.ID.typebutton); mTypebutton.setonClickListener(new ClickListenerImpl()); } // 注册一个针对ContentProvIDer的ContentObserver用来观察内容提供者的数据变化 private voID initContentObserver() { Uri uri = Uri.parse("content://cn.bs.testcontentprovIDer/person"); mContentObserverSubClass=new ContentObserverSubClass(new Handler()); this.getContentResolver().registerContentObserver(uri,true,mContentObserverSubClass); } @OverrIDe protected voID onDestroy() { super.onDestroy(); if (mContentObserverSubClass!=null) { this.getContentResolver().unregisterContentObserver(mContentObserverSubClass); } } // 自定义一个内容观察者ContentObserver private class ContentObserverSubClass extends ContentObserver { public ContentObserverSubClass(Handler handler) { super(handler); } //采用时间戳避免多次调用onChange( ) @OverrIDe public voID onChange(boolean selfChange) { super.onChange(selfChange); System.out.println("ContentObserver onChange() selfChange="+ selfChange); if (System.currentTimeMillis()-lastTime>2000) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://cn.bs.testcontentprovIDer/person"); // 获取最新的一条数据 Cursor cursor = resolver.query(uri,"personID desc limit 1"); while (cursor.movetoNext()) { int personID = cursor.getInt(cursor.getColumnIndex("personID")); System.out.println("内容提供者中的数据发生变化,现数据中第一条数据的personID="+ personID); } cursor.close(); lastTime=System.currentTimeMillis(); }else{ System.out.println("时间间隔过短,忽略此次更新"); } } @OverrIDe public boolean deliverSelfNotifications() { return true; } } private class ClickListenerImpl implements OnClickListener { @OverrIDe public voID onClick(VIEw v) { switch (v.getID()) { case R.ID.addbutton: Person person = null; for (int i = 0; i < 5; i++) { person = new Person("xiaoming" + i,"9527" + i,(8888 + i)); testInsert(person); } break; case R.ID.deletebutton: testDelete(1); break; case R.ID.updatebutton: testUpdate(3); break; case R.ID.querybutton: // 查询表 // queryFromContentProvIDer(-1); // 查询personID=2的数据 testquery(2); break; case R.ID.typebutton: testType(); break; default: break; } } } private voID testInsert(Person person) { ContentValues contentValues=new ContentValues(); contentValues.put("name",person.getname()); contentValues.put("phone",person.getPhone()); contentValues.put("salary",person.getSalary()); Uri insertUri=Uri.parse("content://cn.bs.testcontentprovIDer/person"); Uri returnUri=mContentResolver.insert(insertUri,contentValues); System.out.println("新增数据:returnUri="+returnUri); } private voID testDelete(int index){ Uri uri=Uri.parse("content://cn.bs.testcontentprovIDer/person/"+String.valueOf(index)); mContentResolver.delete(uri,null); } private voID testUpdate(int index){ Uri uri=Uri.parse("content://cn.bs.testcontentprovIDer/person/"+String.valueOf(index)); ContentValues values=new ContentValues(); values.put("name","hanmeimei"); values.put("phone","1234"); values.put("salary",333); mContentResolver.update(uri,null); } private voID testquery(int index) { Uri uri=null; if (index<=0) { //查询表 uri=Uri.parse("content://cn.bs.testcontentprovIDer/person"); } else { //按照ID查询某条数据 uri=Uri.parse("content://cn.bs.testcontentprovIDer/person/"+String.valueOf(index)); } //对应上面的:查询表 //Cursor cursor= mContentResolver.query(uri,null); //对应上面的:查询personID=2的数据 //注意:因为name是varchar字段的,所以应该写作"name='xiaoming1'" // 若写成"name=xiaoming1"查询时会报错 Cursor cursor= mContentResolver.query(uri,"name='xiaoming1'",null); while(cursor.movetoNext()){ int personID=cursor.getInt(cursor.getColumnIndex("personID")); String name=cursor.getString(cursor.getColumnIndex("name")); String phone=cursor.getString(cursor.getColumnIndex("phone")); int salary=cursor.getInt(cursor.getColumnIndex("salary")); System.out.println("查询得到:personID=" + personID+",name="+name+",phone="+phone+",salary="+salary); } cursor.close(); } private voID testType(){ Uri dirUri=Uri.parse("content://cn.bs.testcontentprovIDer/person"); String dirType=mContentResolver.getType(dirUri); System.out.println("dirType:"+dirType); Uri itemUri=Uri.parse("content://cn.bs.testcontentprovIDer/person/3"); String itemType=mContentResolver.getType(itemUri); System.out.println("itemType:"+itemType); } }
Person如下:
package cn.testbaIDu; public class Person { private Integer ID; private String name; private String phone; private Integer salary; public Person(String name,String phone,Integer salary) { this.name = name; this.phone = phone; this.salary=salary; } public Person(Integer ID,String name,Integer salary) { this.ID = ID; this.name = name; this.phone = phone; this.salary=salary; } public Integer getID() { return ID; } public voID setID(Integer ID) { this.ID = ID; } public String getname() { return name; } public voID setname(String name) { this.name = name; } public String getPhone() { return phone; } public voID setPhone(String phone) { this.phone = phone; } public Integer getSalary() { return salary; } public voID setSalary(Integer salary) { this.salary = salary; } @OverrIDe public String toString() { return "Person [ID=" + ID + ",name=" + name + ",phone=" + phone+ ",salary=" + salary + "]"; } }
main.xml如下:
<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" > <button androID:ID="@+ID/addbutton" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:layout_margintop="30dip" androID:text="增加" androID:textSize="20sp" /> <button androID:ID="@+ID/querybutton" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:layout_margintop="30dip" androID:layout_below="@ID/addbutton" androID:text="查询" androID:textSize="20sp" /> <button androID:ID="@+ID/deletebutton" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:layout_margintop="30dip" androID:layout_below="@ID/querybutton" androID:text="删除" androID:textSize="20sp" /> <button androID:ID="@+ID/updatebutton" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:layout_margintop="30dip" androID:layout_below="@ID/deletebutton" androID:text="修改" androID:textSize="20sp" /> <button androID:ID="@+ID/typebutton" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:layout_margintop="30dip" androID:layout_below="@ID/updatebutton" androID:text="类型" androID:textSize="20sp" /> </relativeLayout>
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
总结以上是内存溢出为你收集整理的Android 中自定义ContentProvider与ContentObserver的使用简单实例全部内容,希望文章能够帮你解决Android 中自定义ContentProvider与ContentObserver的使用简单实例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)