新信息存入数据库的更新过程

一般对于数据库更新过程都是要利用到观察者模式,所以在讲解新信息的更新过程前先了解观察者模式的注册和通知更新的流程。

 

注册监听时各个类之间的调用关系

ContentObserver 就是就是用来接收数据变化时的观察者,能进行异步派发派发接收到变化的通知。

public abstract class ContentObserver {

  private Transport mTransport;

  Handler mHandler;

  public ContentObserver(Handler handler) {}

  public IContentObserver getContentObserver() {}

  public void onChange(boolean selfChange) {}   //需要重写onChange

  public final void dispatchChange(boolean selfChange) {}

}

CursorAdapter的初始化函数中,将ContentObserver注册到观察队列中:

void init(Context context, Cursor c, boolean autoRequery) {

  mChangeObserver = new ChangeObserver();// ChangeObserver继承 ContentObserver

  c.registerContentObserver(mChangeObserver); //交给Cursor注册Observer

}

/**********************************************************************/

在短信中注册数据库监听是在GsmSMSDispatcher中注册

ContentResolver cr = mContext.getContentResolver();

cr.registerContentObserver(…);

/**********************************************************************/

Cursor中注册Observer过程中,Cursor只是一个接口真正注册的是它实现者AbstractCursor

public abstract class AbstractCursor implentments CrossProcessCursor{

//CrossProcessCursor 是个interfaceextend Cursor

void registerContentObserver(ContentObserver observer) {

        mContentObservable.registerObserver(observer); //所以最后由mContentObservable完成最后注册

}}

 

ContentObservable类:

public class ContentObservable extends Observable<ContentObserver> {

    public void registerObserver(ContentObserver observer) {}

    public void dispatchChange(boolean selfChange) {}

    public void notifyChange(boolean selfChange) {}

}

public abstract class Observable<T> {

    protected final ArrayList<T> mObservers = new ArrayList<T>();

    public void registerObserver(T observer) {}

    public void unregisterObserver(T observer) {}

    public void unregisterAll() {

}

 

AbstractCursor接收到通知后的更新过程:

1 AbstractCursor作为Subject,那么触发Observer更新是在何时进行呢?AbstractCursor有这样一个接口:

protected void onChange(boolean selfChange) {  //通过onChange函数来通知更新

  mContentObservable.dispatchChange(selfChange); //触发所有的Observer

  if (mNotifyUri != null && selfChange) {

    mContentResolver.notifyChange(mNotifyUri, mSelfObserver);

 }}

2、调用ContentObservable类中的dispatchChange函数:

public void dispatchChange(boolean selfChange) {

 for (ContentObserver observer : mObservers) {

 if (!selfChange || observer.deliverSelfNotifications()) {

  observer.dispatchChange(selfChange); //对于观察队列中的每个ContentObserver调用dispatchChange

 }}}

3、在ContentObserver类中

public final void dispatchChange(boolean selfChange) {

  if (mHandler == null) {

    onChange(selfChange);

  } else {

    mHandler.post(new NotificationRunnable(selfChange));  //异步的派发变化时通知

 }}

 

AbstractCursor对象状态变化通知:

1通知过程可知,AbstractCursor最开始是从其onChange()函数开始的。

而这个函数是由其内部类SelfContentObserver调用的。

 

2、在AbstractCursor内部类SelfContentObserver中有如下:

protected static class SelfContentObserver extends ContentObserver {

  WeakReference<AbstractCursor> mCursor;

  public void onChange(boolean selfChange) {

    AbstractCursor cursor = mCursor.get();

    //这里调用其依赖类的上述的onChange类中

    cursor.onChange(false);  //这里传递的false

 }}

而对于SelfContentObserver内部类,在AbstractCursor中由setNotificationUri()函数调用,
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
 mNotifyUri = notifyUri;
 mContentResolver = cr;
 mSelfObserver = new SelfContentObserver(this); //new一个SelfContentObserver内部类
 mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver); //进行Observer的注册
}
顺着函数调用往上找,该setNotificationUri()函数调用是在:contentProvider中的Query()函数注释中有描述,派生类中需要调用这个c.setNotificationUri()。
setNotificationUri()函数中new完一个内部类后,需要调用ContentResolver将该内部类注册到观察者队列中。
3、ContentResolver中注册Observer
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
           ContentObserver observer){
    getContentService().registerContentObserver(uri, notifyForDescendents,
    observer.getContentObserver());
}
在这里进行Observer注册时调用的是ContentService来进行的。
4、ContentService中注册Observer函数:
public void registerContentObserver(Uri uri, boolean notifyForDescendents,
              IContentObserver observer) {
mRootNode.addObserverLocked(uri, observer,notifyForDescendents, mRootNode,Binder.getCallingUid(), Binder.getCallingPid());
}
看到此函数有三个参数分别代表什么意义呢:
 uri:针对对有变化的感兴趣进行监听的URI
 notifyForDescendents:true表示以uri前缀开始的任何变化都进行通知;false表示完全匹配才进行通知;
 observer:IContentObserver接口,提供了一个方法onChange,变化发生时Cursor需要更新时调用
使用此ContentService的registerContentObserver接口注册Observer,通过指定Uri可以仅对数据库中感兴趣的数据有变化时,进行监听。
以上就是subject注册完了各种observe的监听,然后subject也被ContentService注册到监听数据库,所以现在就是subject等待数据库的变化来通知其注册的observe进行更新。
 
触发数据更新通知:
对数据库中数据的更改操作都是通过ContentResolver 中使用ContentProvider进行修改的,数据变化就来源于此;Insert函数中都执行了:getContext().getContentResolver().notifyChange(newUri, null)
void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
  getContentService().notifyChange(……);
}
在这里通过调用ContentService的notifyChange()函数来继续通知更新
ContentService通知Observer更新
这时在ContentService中只通知感兴趣的observer
public void notifyChange(Uri uri, IContentObserver observer,
  boolean observerWantsSelfNotifications, boolean syncToNetwork) {
  //用于保存对此变化感兴趣的Observer
  ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
  //收集对此变化感兴趣的Observer
  mRootNode.collectObserversLocked(...,calls);
  //发布数据变化通知到相应的Observer
  final int numCalls = calls.size();
  for (int i=0; i<numCalls; i++) {
    ObserverCall oc = calls.get(i);
    oc.mObserver.onChange(oc.mSelfNotify);
 }}
这时更新就已经通知到AbstractCursor中所注册的SelfContentObserver的onChange函数中,然后就到了AbstractCursor作为Subject时这一层的Observer模式的通知机制中。

 

Android中ContentService数据变化通知更新流程
在整个通知流程中的两种Observer模式,一个是CursorAdapter注册应用中的observer,另外一个是CursorAdapter作为一个observer注册到contentService中。

 

结合message应用的注册监听过程:

ConversationListFragment.java
//定义mContentChangedListener变量,并实现了adapter中的change方法
Private final ConversationListAdapter.OnContentChangedListener mContentChangedListener = 
      new ConversationListAdapter.OnContentChangedListener(){//new 了conversationListAdapter的listener接口
Public void onContentChanged(…){ //继承了adapter接口,就必须实现其中的onContentChanged方法
…}
}
在onStart方法或其他方法中注册这个监听器
OnStart(){
mListAadapter.setOnContentChangedListener(mContentChangedListener);//调用adapter中的set方法设置监听

}

 

ConversationListAdapter.java 
//定义了OnContentChangedListener的接口
Public interface OnContentChangedListener{
Void onContentChanged(…);//定义了onContentChanged方法
}
Public void setOnContentChangedListener(onContentChangedListener l){//在adapter定义设置监听的方法
mOnContentChangedListener = l;
}
@override
Protect void onContentChanged(){ //重写了父类cursorAdapter.java 中的onContentChanged方法
mOnContentChangedListener.onContentChanged();//当onContentChanged方法被调用后,
其执行的是调用conversationListFragment中的onContentChanged方法,因为mOnContentChangedListener是
在conversationListFragment函数的onstart方法中通过adapter的set方法设置好了监听。
}

 

cursorAdapter.java    
//ConversationListAdapter.java 继承了cursorAdapter.java 
在cursorAdapter.java的init类中
void init(Context context, Cursor c, boolean autoRequery) {
  // ChangeObserver 继承 ContentObserver
  mChangeObserver = new ChangeObserver();
  //交给Cursor注册Observer
c.registerContentObserver(mChangeObserver);
//由于mChangeObserver是ChangeObserver的对象,继承了ContentObserver类,注册是通过cursor 的对象C 进行的,
   所以是有cursor来真正实现注册 mChangeObserve。
//在Cursor是一个接口真正干活的是它实现者AbstractCursor
mContentObservable.registerObserver(observer);  AbstractCursor这里作为Subject接收注册Observer。
}

 

Private class ChangeObserver extends ContentObserver{  
//类ChangedOberver是cursorAdapter的内部类,并继承了ConentObserver
@override
Public void onChange(Boolean selfChange){
onContentChanged();}
}
Protect void onContentChanged(){
mDataValid = mCursor.requery();//真正执行requery函数
}
这样整个监听的过程就结束了。
首先在conversationListFragment和conversationListAdapter中定义了contentChanged方法。
再通过cursorAdapter在init函数中去注册监听,将其内部类changeObserver的对象通过cursor类去注册到AbstractCursor这个subject中的
最后AbstractCursor作为subject类管理所有已经注册的Observer。
 

而此时AbstractCursor又作为observer又要去注册contentService作为subject的监听。

所以最后整个注册监听过程是从最初的cursorAdapter把其内部类changeObserver(继承了contentObserver)通过cursor注册到AbstractCursor,这是AbstractCursor作为subject去管理注册的observer。接下来AbstractCursor 仍然需要作为observer继续注册到contentService中,监听contentService的变化。

 

 

接下来分析新信息更新过程:
更新过程的源头是数据库发生了变化,当调用insert,delete或者update方法时,数据库发生改变,而代码会在这三个方法调用的最后加上。

IccProvide.java
Public Uri insert(){
getContext().getContentResolver().notifyChange();//调用contentReslove开始触发更新过程
}

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/kma-3/p/9879656.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值