工作中碰到开启一个线程做大量的查询,来检测某个数据库值发送了变化,这样开销很大,后来利用了ContentObserver完美的解决了该问题。

(1)ContentObserver——目的是观察(捕捉)特定Uri数据库的变化,继而做一些相应的处理,它类似于数据库中的触发器,当所察的Uri发生变化时,便会触发它。它的主要方法有:

       A,public final void  registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer),功能:为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。参数:uri,需要观察的Uri;notifyForDescendents,为false表示精确匹配,即只匹配该Uri,为true表示可以同时匹配其派生的Uri,一般为true;observer,ContentObserver的派生类实例。

       B,public final void  unregisterContentObserver(ContentObserver observer),功能:取消对给定Uri的观察

       C,public void ContentObserver(Handler handler),功能:所有ContentObserver的派生类都需要调用该构造方法。参数:handler,Handler对象。可以是主线程Handler(这时候可以更新UI 了),也可以是任何Handler对象。

       D,void onChange(boolean selfChange),功能:当观察到的Uri发生变化时,回调该方法去处理。所有ContentObserver的派生类都需要重载该方法去处理逻辑。

(2)使用ContentObserver的前提是系统数据库中已经有这个变量,建立这个变量的方法是修改frameworks/base/core/java/android/provider/Settings.java,比如要添加属性“SILVAN_LIU”,则

 public static final String SILVAN_LIU = "silvan_liu";  
 public static final String[] SETTINGS_TO_BACKUP ={  
            ~  
       +SILVAN_LIU  
              ~     
}  

这样添加后,你就可以通过Settings.System.getInt(getContentResolver(), Settings.System.SILVAN_LIU,0) 和Settings.System.putInt(getContentResolver(), Settings.System.SILVAN_LIU,0)去得到和设定SILVAN_LIU的属性值。
(3)一个实例,用来监控当设置中的开关切换时,对应的服务要打开或者关闭(图标显示或隐藏)。

       需要导入的类:

import android.content.ContentResolver;
import android.database.ContentObserver;

       全局变量:

ContentResolver cr = null;

      在服务的onCreate中完成:

cr = mContext.getContentResolver();
cr.registerContentObserver(
			Uri.parse("content://settings/system/xxxx"),   //监听的URI值对象
			true,
			m_xxxxyObserver);		//ContentObserver实例,在外面定义

        在服务类中完成ContentObserver实例的构造,以及完成onChange重载处理:

	private ContentObserver m_xxxxObserver = new ContentObserver(new Handler()){
		public void onChange(boolean selfChange){
			updateSettingsValues();
		}
	};
	
	private void updateSettingsValues() {
		mIsxxxxOn= Settings.System.getInt(cr,"isxxxxEnabled",0) == 1 ? true : false;
		if(mIsxxxxyOn == true){
			//开启服务,显示图标
		}
		else{
			//关闭服务,隐藏图标
		}
	}

         在服务的onDestroy函数中,必须反注册这个ContentObserver:

cr.unregisterContentObserver(m_xxxxObserver);

(3)总结:使用ContentObserver的情况主要有一下两者情况:A,需要频繁检测的数据库或者某个数据是否发生改变,如果使用线程去操作,很不经济而且很耗时 ;B,在用户不知晓的情况下对数据库做一些事件,比如:悄悄发送信息、拒绝接受短信黑名单等;