第三篇 android 应用开发模式之MVC模式及Observer模式

如果说模板模式是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");

    }

}


 

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

你可能感兴趣的:(android,MVC模式,observer模式,应用开发模式)