欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android开发中ContentObserver类的使用

程序员文章站 2024-02-28 20:43:40
contentobserver——内容观察者,目的是观察(捕捉)特定uri引起的数据库的变化,继而做一些相应的处理,它类似于 数据库技术中的触发器(trigger),当c...

contentobserver——内容观察者,目的是观察(捕捉)特定uri引起的数据库的变化,继而做一些相应的处理,它类似于
数据库技术中的触发器(trigger),当contentobserver所观察的uri发生变化时,便会触发它。触发器分为表触发器、行触发器,
相应地contentobserver也分为“表“contentobserver、“行”contentobserver,当然这是与它所监听的uri mime type有关的。

熟悉content provider(内容提供者)的应该知道,我们可以通过urimatcher类注册不同类型的uri,我们可以通过这些不同的
uri来查询不同的结果。根据uri返回的结果,uri type可以分为:返回多条数据的uri、返回单条数据的uri。

注册/取消注册contentobserver方法,抽象类contentresolver类中的方法原型如下:

public final void registercontentobserver(uri uri, boolean notifyfordescendents, contentobserver observer)
功能:为指定的uri注册一个contentobserver派生类实例,当给定的uri发生改变时,回调该实例对象去处理。
参数:uri,需要观察的uri(需要在urimatcher里注册,否则该uri也没有意义了)
notifyfordescendents  为false 表示精确匹配,即只匹配该uri
为true 表示可以同时匹配其派生的uri,举例如下:
假设urimatcher 里注册的uri共有一下类型:
1 、content://com.qin.cb/student (学生)
2 、content://com.qin.cb/student/#
3、content://com.qin.cb/student/schoolchild(小学生,派生的uri)

假设我们当前需要观察的uri为content://com.qin.cb/student,如果发生数据变化的 uri 为  
content://com.qin.cb/student/schoolchild ,当notifyfordescendents为 false,那么该contentobserver会监听不到, 
但是当notifyfordescendents 为ture,能捕捉该uri的数据库变化。

observer       contentobserver的派生类实例

public final void unregistercontentobserver(contentobserver observer)

功能:取消对给定uri的观察
参数: observer contentobserver的派生类实例

contentobserver类介绍

构造方法 public void contentobserver(handler handler) 
说明:所有   contentobserver的派生类都需要调用该构造方法
参数: handler  handler对象。可以是主线程handler(这时候可以更新ui 了),也可以是任何handler对象。
常用方法

void onchange(boolean selfchange)

功能:当观察到的uri发生变化时,回调该方法去处理。所有contentobserver的派生类都需要重载该方法去处理逻辑。
参数:selfchange 回调后,其值一般为false,该参数意义不大(我也不懂,理解方法最重要)。

另外两个方法,用处不大,我也不懂,大家参照sdk自行理解,冒昧了。
boolean  deliverselfnotifications()
说明:returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with.

final void dispatchchange(boolean selfchange)


观察特定uri的步骤如下:

1、创建我们特定的contentobserver派生类,必须重载父类构造方法,必须重载onchange()方法去处理回调后的功能实现
2、利用context.getcontentresolover()获得contentresolove对象,接着调用registercontentobserver()方法去注册内容观察者
3、由于contentobserver的生命周期不同步于activity和service等,因此,在不需要时,需要手动的调用
unregistercontentobserver()去取消注册。   

好了,基本讲解就介绍到这儿了。下面给出小demo的简单说明:
demo*有两个不同的contentobserver派生类,如下:
1、用来观察系统是否改变了飞行模式状态,
ps: 大家可以去sdk中查看该类:android.provider.settings.system。该类封装了对设置模块下所有值的存取,比如:
飞行模式状态、蓝牙状态、屏幕亮度值等,并且提供了相应的uri。
2、观察系统的短信息数据发生了变化。当监听到短信数据发生变化时,查询所有已发送的短信并且显示出来。

短信的uri共有一下几种:

  • content://sms/inbox     收件箱        
  • content://sms/sent        已发送
  • content://sms/draft        草稿          
  • content://sms/outbox    发件箱           (正在发送的信息)
  • content://sms/failed      发送失败    
  • content://sms/queued  待发送列表  (比如开启飞行模式后,该短信就在待发送列表里)

使用举例:

package com.example.android_contentobserver;
 
import android.app.activity;
import android.database.contentobserver;
import android.database.cursor;
import android.net.uri;
import android.os.bundle;
import android.os.handler;
 
public class mainactivity extends activity {
 
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
     
    //注册观察者observser
    this.getcontentresolver().registercontentobserver(uri.parse("content://sms"),true,new smsobserver(new handler()));
 
  }
 
  private final class smsobserver extends contentobserver {
 
    public smsobserver(handler handler) {
      super(handler);
 
    }
 
   
    @override
    public void onchange(boolean selfchange) {
 
      cursor cursor = mainactivity.this.getcontentresolver().query(
          uri.parse("content://sms/inbox"), null, null, null, null);
 
      while (cursor.movetonext()) {
        stringbuilder sb = new stringbuilder();
 
        sb.append("address=").append(
            cursor.getstring(cursor.getcolumnindex("address")));
 
        sb.append(";subject=").append(
            cursor.getstring(cursor.getcolumnindex("subject")));
 
        sb.append(";body=").append(
            cursor.getstring(cursor.getcolumnindex("body")));
 
        sb.append(";time=").append(
            cursor.getlong(cursor.getcolumnindex("date")));
 
        system.out.println("--------has receivered sms::" + sb.tostring());
 
         
      }
 
    }
 
  }
}