首页 > 代码库 > 内容观察者

内容观察者

在Android项目中我们常常需要检测另一个应用私有数据的变化与否,如何检测另一个数据库应用中的数据变化,我们通过下面的案例来讲述具体的操作。
应用场景:有两个应用,一个是“01_数据库应用”,另一个是“07_内容观察者”;第二个应用监测第一个应用数据库的变化,当第一个应用数据库发生变化便即时通知第二个应用。实现方法如下:
轮询
若要监测数据库中数据的变化与否,我们可以在当前应用中编写一个定时器,该定时器的工作是每隔一段时间查询数据库中的数据,将查询的结果与之前查询的数据库记录进行对比从而实现监测的目的。
这种方法虽然可行,但是效率低且内存消耗大,因此并不推举。
观察者
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关。
这种方式效率高内存消耗少,在项目中应该使用这种方法。
编写代码
01_数据库应用中定义了一个数据库person.db并注册了该数据库的内容提供者,下面我们通过内容观察者来监听该数据库应用的变化,实现代码如下:
  •   新建另一个应用“07_内容观察者的原理”,在该应用的主Activity中编写例1-1代码:
例1-1        注册内容观察者
  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3.         super.onCreate(savedInstanceState);
  4.         setContentView(R.layout.activity_main);
  5.         // 该uri路径指向数据库应用中的数据库info表
  6.         Uri uri = Uri.parse("content://com.itheima.db/info/");
  7.     //注册内容观察者,参数uri指向要监测的数据库info表,参数true定义了监测的范围,最后一个参数是一个内容观察者对象
  8.         getContentResolver().registerContentObserver(uri, true,
  9. new MyObserver(new Handler()));
  10.         
  11. }
复制代码
例1-1实现了内容观察者的注册工作,即当数据库应用中的数据变化了该应用便可以监测到。在上述代码块中有一个参数new MyObserver(new Handler()),MyObserver是一个观察者对象,继承ContentObserver并实现了onChange方法。具体代码如例1-2所示
例1-1        MyObserver.class
  1. private class MyObserver extends ContentObserver{
  2.         public MyObserver(Handler handler) {//handler 是一个消息处理器。
  3.                 super(handler);
  4.         }
  5.         @Override
  6.    //当info表中的数据发生变化时则执行该方法
  7.         public void onChange(boolean selfChange) {
  8.                 System.out.println("哈哈数据库的内容变化了");
  9.                 super.onChange(selfChange);
  10.         }
  11. }
复制代码
  •   01_数据库应用中添加通知数据库变化的代码,具体代码如下:
当新加一条数据记录时,此时数据库info表会发生变化,因此我们需调整添加代码如例1-3所示:
例1-3
  1. @Override
  2. public Uri insert(Uri uri, ContentValues values) {
  3.         int code = mUriMatcher.match(uri);
  4.         if (code == SUCCESS) {
  5.                 SQLiteDatabase db = helper.getWritableDatabase();
  6.                 long id = db.insert("info", null, values);
  7.                 db.close();
  8.                 //content://com.itheima.db/info/5
  9.                 //大吼一声,讲数据库的内容变化了。
  10.                 getContext().getContentResolver().notifyChange(uri, null);
  11.                 return Uri.parse("content://com.itheima.db/info/"+id);
  12.         }else{
  13.                 throw new IllegalArgumentException("uri 不匹配");
  14.         }
  15. }
复制代码
当删除一条数据记录时,此时数据库info表会发生变化,因此我们需调整添加代码如例1-4所示:
例1-4
  1. @Override
  2. public int delete(Uri uri, String selection, String[] selectionArgs) {
  3.         int code = mUriMatcher.match(uri);
  4.         if (code == SUCCESS) {
  5.                 SQLiteDatabase db = helper.getWritableDatabase();
  6.                 int result = db.delete("info", selection, selectionArgs);
  7.                 db.close();
  8.                 if(result>0){
  9.                 //大吼一声,讲数据库的内容变化了。
  10.                 getContext().getContentResolver().notifyChange(uri, null);
  11.                 }
  12.                 return result;
  13.         }else{
  14.                 throw new IllegalArgumentException("uri 不匹配");
  15.         }
  16. }
 
 
 
 
 

内容观察者