如果说模板模式是ANDROID框架的核心,提供了应用程序架构组件的基础,Observer模式则提供了ANDROD架构连接件的基础,同时也是另外两个组件广播组件及内容提供者组件的实现基础,还是UI输入机制的基础。Observer模式在android应用程序及框架中普遍采用。

Observer模式也称作发布/订阅模式,实现机理是消息发布/订阅模式的事件驱动模型:消息的生产者发布事件,而使用者订阅感兴趣的事件。

我们知道Observer模式是MVC模式的基础,而 MVC模式是ANDROID框架隐藏的一个重要模式。在ANDROID框架看来ACTIVITY连同其基类ContextImpl担负着MVC模式中的控制器Controller)角色,用来转发视图发送的控制请求,并和模型(Model)交互;而ACTIVITY绑定的视图(DecorView),在MVC模式中也起到视图(VIEW)角色,DecorViewACTIVITY的主视图,其它子视图或控件都由ACTIVITY通过读取应用程序的布局文件(XML格式)生成,并组合成视图树,实现视图的布局(视图采用了组合模式组合成视图树)。而框架的每一个服务及其产生的数据则提供了MVC模型(Model)的角色。而每个服务通过ContextImpl中登记的本地服务管理对象进行控制,视图也通过控制器(ContextImpl)登记对模型事件的监听,控制器本身也可以登记为监听对象。本地服务管理对象本身或者应用程序视图通过本地服务管理对象Controller)向模型发出请求消息和服务(Model)交互,服务产生的数据发生变化时,通过Observer模式(广播或INTENT)通知视图和控制器。在MVC模式中视图是观察者Observer,视图通过组合模式组合成视图树,控制器担当视图和模型的中介者,因此这里的MVC模式是采用Observer模式、组合模式、中介模式的复合模式。

采用MVC模式可以简化应用程序的开发,而通过框架提供模型控制器的实现则使应用程序的开发更加容易。应用程序只需继承控制器(ACTIVITY)和实现回调接口、编写VIEW的布局XML文件、提供用到的资源文件、注册对模型的监听事件、编写与模型提供数据的接口(ANDROID又是推荐采用Adapter模式实现与各种数据源接口,ANDROID为此针对数据库提供了SimpleCursorAdapter类)等五个任务就可完成应用程序的开发。而业务逻辑及数据提供、转发视图的控制请求都交给框架处理好了,应用开发如此简单。下面看一个ACTIVITY的具体例子。

    private BroadcastReceiver mScanListener = new BroadcastReceiver() {//实例化一个广播对象        @Override        public void onReceive(Context context, Intent intent) {//实现广播接收回调接口            MusicUtils.setSpinnerState(AlbumBrowserActivity.this);            mReScanHandler.sendEmptyMessage(0);            if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {                MusicUtils.clearAlbumArtCache();            }        }    };public class  MyActivity extends Activity implements OnItemClickListener {    @Override       protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);       IntentFilter f = new IntentFilter();        f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);        f.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);        f.addAction(Intent.ACTION_MEDIA_UNMOUNTED);        f.addDataScheme("file");        registerReceiver(mScanListener, f);//注册对模型的广播监听事件        setContentView(R.layout.media_picker_activity);//读取布局文件生成视图树 Cursor c = getContentResolver().query(Settings.System.CONTENT_URI, null, null, null, null);//首先通过控制器获得数据源的指针 ListAdapter adapter = new SimpleCursorAdapter(this,               android.R.layout.simple_list_item_1,                  c,                 new String[] {People.NAME} ,                new int[] {android.R.id.text1}); setListAdapter(adapter);//采用Adapter模式设置与数据源的接口 getListView().setOnItemClickListener(this);//设置视图控件的监听者,控制器监听    }    public void onItemClick(AdapterView parent, View view, int position, long id) {//视图监听事件的回调接口        Intent dummyIntent = new Intent(this, ListSimple.class);        startActivity(dummyIntent);}

ContextImpl中采用静态代码块的方法把总共34系统服务管理对象预先登记到ContextImpl的CACHE中,视图或控制器对象通过getSystemService接口统一从cache获取服务管理对象,实现与模型的交互。由于这种方式实现了对象只在包装载时实例化一次,并登记到cache,因此能够实现提高获取系统服务管理对象的速度的目的。

   private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =            new HashMap<String, ServiceFetcher>();//实例化保存fetcher对象的HashMap,fetcher对象实际完成读取本地服务管理对象的目的。 private static void registerService(String serviceName, ServiceFetcher fetcher) {        if (!(fetcher instanceof StaticServiceFetcher)) {            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;        }        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);//根据服务名字把fetcher对象放到HashMap中    }    static {        registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {                public Object getService(ContextImpl ctx) {                    return AccessibilityManager.getInstance(ctx);                }});//把一个fetcher对象登记到ACCESSIBILITY_SERVICE服务名字对应的HashMap中,并覆盖getService函数         registerService(ACCOUNT_SERVICE, new ServiceFetcher() {                public Object createService(ContextImpl ctx) {                    IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);                    IAccountManager service = IAccountManager.Stub.asInterface(b);                    return new AccountManager(ctx, service);                }});//把一个fetcher对象登记到ACCOUNT_SERVICE服务名字对应的HashMap中,并实现其createService接口。 … } static class ServiceFetcher {public Object getService(ContextImpl ctx) {            ArrayList<Object> cache = ctx.mServiceCache;            Object service;            synchronized (cache) {                if (cache.size() == 0) {                    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {                        cache.add(null);                    }                } else {                    service = cache.get(mContextCacheIndex);//从cache中获取服务                    if (service != null) {                        return service;                    }                }                service = createService(ctx);// 在cache中获取不到则实例化服务管理对象。                cache.set(mContextCacheIndex, service);//重新把新创建的服务管理对象放到cache中,供下次使用。                return service;            }        }}    @Override    public Object getSystemService(String name) {//获取本地服务管理对象统一接口        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);        return fetcher == null ? null : fetcher.getService(this);//通过fetcher的getService接口获取本地服务管理对象。    }

框架中Observer模式大量采用,包括JNI向JAVA层发送通知等。android_media_MediaPlayer.cpp文件

static void android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this){    LOGV("native_setup");    sp<MediaPlayer> mp = new MediaPlayer();   sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);    mp->setListener(listener);// 登记C++层媒体播放器的监听器为一个JNI对象。}void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj){    JNIEnv *env = AndroidRuntime::getJNIEnv();    if (obj && obj->dataSize() > 0) {…            env->CallStaticVoidMethod(mClass, fields.post_event, mObject,                    msg, ext1, ext2, jArray);//在这里JNI监听器对象转发播放器产生的事件    } }void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj){    sp<MediaPlayerListener> listener = mListener;    if ((listener != 0) && send) {        listener->notify(msg, ext1, ext2, obj); //播放器产生事件的回调接口在这里向JNI  listener对象发送通知。        LOGV("back from callback");    }}


上一篇版权所有,转载时请尊重原创显要位置注明链接,谢谢!下一篇

更多相关文章

  1. 【设计模式与Android】原型模式——复制中心走出来的克隆人
  2. android ICS 4.0.3 tablet模式 插入usb线 不提示sd卡已连接 解决
  3. 安卓开机logo和开机动画的几种实现方法
  4. android省电开发之cpu降频
  5. 跟Google学习Android开发-起始篇-构建你的第一个应用程序(3)
  6. [置顶] android 从资源中获取数组
  7. Android平台上大长图(图片很大的那种)的加载原理和方式
  8. java/android 设计模式学习笔记(18)---中介者模式
  9. 2019年Android开发者常见面试题(一)

随机推荐

  1. android 事件总线 -- Otto(一)
  2. android文档开发规范
  3. 初涉Android蓝牙开发
  4. Android远程服务三:android AIDL远程服务
  5. Android(安卓)UI设计技巧
  6. Android实现天气预报温度/气温折线趋势图
  7. cocos2dx在windows下开发,编译到android上
  8. 听说”双11”是这么解决线上bug的
  9. Android尺寸单位
  10. Android(安卓)获取屏幕尺寸与密度