編輯:Android開發實例
//contentObserver只是通知數據庫中內容變化了
cursor.registerContentObserver(mChangeObserver);
//datasetObserver是調用requery之後通知上層cursor數據內容已經更新
cursor.registerDataSetObserver(mDataSetObserver);
我們的調用流程如下:
當我們使用getContentResolver().query()的時候,我們的resolver會通過uri找到對應的provider,調用相應的query()方法,
該方法中的部分內容:
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor ret = qb.query(db, projection, selection,selectionArgs, null, null, finalSortOrder);
// TODO: Does this need to be a URI for this provider.
ret.setNotificationUri(getContext().getContentResolver(), uri);
return ret;
Cursor本身只是接口,實際調用的應該是AbstractCursor
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
synchronized (mSelfObserverLock) {
mNotifyUri = notifyUri;
mContentResolver = cr;
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
}
mSelfObserver = new SelfContentObserver(this);
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
mSelfObserverRegistered = true;
}
}
//AbstractCursor的內部類
protected static class SelfContentObserver extends ContentObserver {
WeakReference<AbstractCursor> mCursor;
public SelfContentObserver(AbstractCursor cursor) {
super(null);
mCursor = new WeakReference<AbstractCursor>(cursor);
}
@Override
public boolean deliverSelfNotifications() {
return false;
}
@Override
public void onChange(boolean selfChange) {
AbstractCursor cursor = mCursor.get();
if (cursor != null) {
cursor.onChange(false);
}
}
}
ContentObservable mContentObservable = new ContentObservable(); //AbstractCursor持有的contentObservable
//AbstractCursor的onchange()
protected void onChange(boolean selfChange) {
synchronized (mSelfObserverLock) {
mContentObservable.dispatchChange(selfChange);
if (mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri, mSelfObserver); //selfChange = false
}
}
}
AbstractCursor中
public void registerContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
在ContentObservable中
public void dispatchChange(boolean selfChange) {
synchronized(mObservers) {
for (ContentObserver observer : mObservers) {
if (!selfChange || observer.deliverSelfNotifications()) {
observer.dispatchChange(selfChange);
}
}
}
}
在CursorAdapter中我們注冊了ContentObserver
private class ChangeObserver extends ContentObserver {
public ChangeObserver() {
super(new Handler());
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
@Override
public void onChange(boolean selfChange) {
onContentChanged();
}
}
//父類的方法
public final void dispatchChange(boolean selfChange) {
if (mHandler == null) {
onChange(selfChange);
} else {
mHandler.post(new NotificationRunnable(selfChange));
}
}
//父類的內部類
private final class NotificationRunnable implements Runnable {
private boolean mSelf;
public NotificationRunnable(boolean self) {
mSelf = self;
}
public void run() {
ContentObserver.this.onChange(mSelf);
}
}
在CursorAdapter中
protected void onContentChanged() {
if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
if (Config.LOGV) Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
mDataValid = mCursor.requery();
}
}
在AbstractCursor中
public boolean requery() {
if (mSelfObserver != null && mSelfObserverRegistered == false) {
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
mSelfObserverRegistered = true;
}
mDataSetObservable.notifyChanged(); //任何繼承AbstractCursor的Cursor都將通過調用super.requery()執行此句
return true;
}
如果我們注冊了dataset的observer,就會得到相應的通知。
總結:
contentObserver是一個提前通知,這時候只是通知cursor說,我的內容變化了。
datasetObserver是一個後置通知,只有通過requery() deactivate() close()方法的調用才能獲得這個通知。
因此,最為重要的還是ContentObserver,它可以告訴你數據庫變化了,當然如果你要在更新完Cursor的dataset之後做一些
事情,datasetObserver也是必需的。
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放