如果說模板模式是ANDROID架構的核心,提供了應用程式架構組件的基礎,而Observer模式則提供了ANDROD架構串連件的基礎,同時也是另外兩個組件廣播組件及內容提供者組件的實現基礎,還是UI輸入機制的基礎。Observer模式在android應用程式及架構中普遍採用。
Observer模式也稱作發布/訂閱模式,實現機理是訊息發布/訂閱模式的事件驅動模型:訊息的生產者發布事件,而使用者訂閱感興趣的事件。
我們知道Observer模式是MVC模式的基礎,而 MVC模式是ANDROID架構隱藏的一個重要模式。在ANDROID架構看來ACTIVITY連同其基類ContextImpl擔負著MVC模式中的控制器(Controller)角色,用來轉寄視圖發送的控制請求,並和模型(Model)互動;而ACTIVITY綁定的視圖(DecorView),在MVC模式中也起到視圖(VIEW)角色,DecorView是ACTIVITY的主視圖,其它子視圖或控制項都由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");
}
}
歡迎轉載,轉載時請尊重原創註明出處。