ContentObserver——內容觀察者,目的是觀察(捕捉)特定Uri引發的數據庫的變化,繼而作一些相應的處理,它相似於數據庫
數據庫技術中的觸發器(Trigger),當ContentObserver所觀察的Uri發生變化時,便會觸發它。觸發器分爲表觸發器、行觸發器,app
相應地ContentObserver也分爲「表「ContentObserver、「行」ContentObserver,固然這是與它所監聽的Uri MIME Type有關的。ide
熟悉Content Provider(內容提供者)的應該知道,咱們能夠經過UriMatcher類註冊不一樣類型的Uri,咱們能夠經過這些不一樣的ui
Uri來查詢不一樣的結果。根據Uri返回的結果,Uri Type能夠分爲:返回多條數據的Uri、返回單條數據的Uri。this
註冊/取消註冊ContentObserver方法,抽象類ContentResolver類中的方法原型以下:spa
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)線程
功能:爲指定的Uri註冊一個ContentObserver派生類實例,當給定的Uri發生改變時,回調該實例對象去處理。rest
參數:uri 須要觀察的Uri(須要在UriMatcher裏註冊,不然該Uri也沒有意義了)orm
notifyForDescendents 爲false 表示精確匹配,即只匹配該Uriserver
爲true 表示能夠同時匹配其派生的Uri,舉例以下:
假設UriMatcher 裏註冊的Uri共有一下類型:
1 、content://com.qin.cb/student (學生)
2 、content://com.qin.cb/student/#
三、 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的步驟以下:
一、 建立咱們特定的ContentObserver派生類,必須重載父類構造方法,必須重載onChange()方法去處理回調後的功能實現
二、 利用context.getContentResolover()得到ContentResolove對象,接着調用registerContentObserver()方法去註冊內容觀察者
三、 因爲ContentObserver的生命週期不一樣步於Activity和Service等,所以,在不須要時,須要手動的調用
unregisterContentObserver()去取消註冊。
若是ContentProvider的訪問者須要知道ContentProvider中的數據發生了變化,能夠在ContentProvider 發生數據變化時調用getContentResolver().notifyChange(uri, null)來通知註冊在此URI上的訪問者,例子以下:
public class PersonContentProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
db.insert("person", "personid", values);
getContext().getContentResolver().notifyChange(uri, null);
}
}
若是ContentProvider的訪問者須要獲得數據變化通知,必須使用ContentObserver對數據(數據採用uri描述)進行監聽,當監聽到數據變化通知時,系統就會調用ContentObserver的onChange()方法:
getContentResolver().registerContentObserver(Uri.parse("content://cn.itcast.providers.personprovider/person"),
true, new PersonObserver(new Handler()));
public class PersonObserver extends ContentObserver{
public PersonObserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange) {
//此處能夠進行相應的業務處理
}
}
l 竊聽用戶發出的短信
用戶使用系統自帶的短信程序發送短信,程序會經過ContentProvider把短信保存進數據庫,而且發出一個數據變化通知,使用ContentObserver對數據變化進行監聽,在用戶發送短信時,就會被ContentObserver竊聽到短信:
註冊監聽:
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));
監聽類:
private final class SmsObserver extends ContentObserver{
public SmsObserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange) {//查詢發送箱中的短信(處於正在發送狀態的短信放在發送箱)
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/outbox"),null, null, null, null);
while(cursor.moveToNext()){
StringBuilder sb = new StringBuilder();
sb.append("_id=").append(cursor.getInt(cursor.getColumnIndex("_id")));
sb.append(",address=").append(cursor.getString(cursor.getColumnIndex("address")));
sb.append(";body=").append(cursor.getString(cursor.getColumnIndex("body")));
sb.append(";time=").append(cursor.getLong(cursor.getColumnIndex("date")));
Log.i("ReceiveSendSMS", sb.toString());
} }