Android与设计模式——观察者(Observer)模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述观察者(Observer)模式的:

  观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。


观察者模式的结构
  一个软件系统里面包含了各种对象,就像一片欣欣向荣的森林充满了各种生物一样。在一片森林中,各种生物彼此依赖和约束,形成一个个生物链。一种生物的状态变化会造成其他一些生物的相应行动,每一个生物都处于别的生物的互动之中。

  同样,一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其他的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作。观察者模式是满足这一要求的各种设计方案中最重要的一种。(上文源于网络)



上图是观察者模式的基本模型,以通话状态(CallState)为例,来分析手机通话状态变化时,是怎么传递这个事件的。

RegistrantList作为通知者,Registrant为观察者,RegistrantList通知者提供了add、remove、notifyRegistrants来管理Registrant。

1、通话状态是怎么被监听的?

mCallStateRegistrants是RegistrantList的一个对象,在BaseCommand.java中生成,并对RegistrantList通知者的添加、删除做了封装

protected RegistrantList mCallStateRegistrants = new RegistrantList();

    public void registerForCallStateChanged(Handler h, int what, Object obj) {
        Registrant r = new Registrant (h, what, obj);//观察者

        mCallStateRegistrants.add(r);
    }

    public void unregisterForCallStateChanged(Handler h) {
        mCallStateRegistrants.remove(h);
    }

registerForCallStateChanged中new了一个Registrant观察者,将其加入到通知者中,来看Registrant是怎么存储的?

    public synchronized void
    add(Registrant r)
    {
        removeCleared();
        registrants.add(r);
    }
registrants是一个 ArrayList对象,管理Registrant其实就是对 ArrayList的操作。

registerForCallStateChanged是在GsmCallTracker.java的构造函数被调用的:

mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
this就是GsmCallTracker本身,GsmCallTracker继承了Handler,此处,也就是说GsmCallTracker成为了观察者,当CallState变化时mCallStateRegistrants应该通知GsmCallTracker。
当不需要监听时,可注销:

mCi.unregisterForCallStateChanged(this);


2、mCallStateRegistrants是怎么通知GsmCallTracker CallState变化了?
在手机中,当通话状态发生改变,Modem会向上传递消息,传到framework时,被RIL.java接收处理:

            case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
                if (RILJ_LOGD) unsljLog(response);

                mCallStateRegistrants
                    .notifyRegistrants(new AsyncResult(null, null, null));
            break;

mCallStateRegistrants使用notifyRegistrants来通知它的所有观察者:

    public /*synchronized*/ void
    notifyResult(Object result)
    {
        internalNotifyRegistrants (result, null);
    }

    private synchronized void
    internalNotifyRegistrants (Object result, Throwable exception)
    {
       for (int i = 0, s = registrants.size(); i < s ; i++) {
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result, exception);
       }
    }

registrants就是之前存储所有观察者的ArrayList,遍历,通知。

3、观察者Registrant是怎么响应处理通知的?

上面看到r.internalNotifyRegistrant(result, exception),观察者知道callstate发生变化后,谁来真正处理?

Registrant部分代码:

    internalNotifyRegistrant (Object result, Throwable exception)
    {
        Handler h = getHandler();

        if (h == null) {
            clear();
            /// M: Registrant Debug Log Enhancement
            Log.d("Registrant", "internalNotifyRegistrant(): Warning! Handler is null, it could be already GCed. ( what=" + what + ", userObj=" + userObj + ", result=" + result + ", exception=" + exception + " )");
        } else {
            Message msg = Message.obtain();

            msg.what = what;
            
            msg.obj = new AsyncResult(userObj, result, exception);
            
            h.sendMessage(msg);
        }
    }
Handler h = getHandler();获得的Handler就是上文说到的this,也就是GsmCallTracker,what就是registerForCallStateChanged注册时的第二个参数EVENT_CALL_STATE_CHANGE,这里h.sendMessage也就是用的GsmCallTracker这个Handler发送的消息。我们都知道,Handler发送的消息都会被它自己的handleMessage()方法所接收处理。

于是,我们在GsmCallTracker的handleMessage()方法中看到:

            case EVENT_CALL_STATE_CHANGE:
                pollCallsWhenSafe();
            break;
具体做什么操作,我们就不管了。。。

Android Telephony源码中用到了大量的观察者模式,理解观察者模式,有助于我们阅读源码。

未完待续,有不对的地方,请指正。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。