android之Context對各種服務的管理

來源:互聯網
上載者:User

android之Context對各種服務的管理

常常,當我們需要用到服務的時候可以通果Context來擷取:Context.getSystemService(name);比如:當我們想知道當前電話狀態(來電/去電/sim卡狀態等)時候,我們可以通過Context來擷取TelephonyManager:

final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

你可知道,為什麼可以通過Context來擷取各種服務嗎?下面來看看.

我們知道,Context的實作類別其實是:ContextImpl,所以我們來看看ContextImpl有上面東西.通過程式碼分析,會很快知道:在ContextImpl中通過原廠模式和單列模式在建立和儲存各個服務物件的.比較複雜,所以下面一個一個的介紹:

(1)在ContextImpl中定義如下一個HashMap,

private static final HashMap SYSTEM_SERVICE_MAP = new HashMap();

這是一個靜態/final的HashMap,其中儲存的是每一個服務的ServiceFetcher.其中,String標識當前服務名,ServiceFetcher是這個服務的工具類!其實就是用來建立該服務的對象.

當我們通過getSystemService(String name)來擷取這個服務時候,就是通過這個ServiceFetcher來得到我們需要的服務的:

 

    public Object getSystemService(String name) {        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);        return fetcher == null ? null : fetcher.getService(this);    }
如上代碼可知:其實是通過 ServiceFetcher的getService()來擷取的.

 

(2)所以我們重點來看看ServiceFetcher實現什麼功能,ServiceFetcher其實是一個簡單的原廠模式設計思路,並且還使用來單列模式! 當通過getService()來擷取服務物件的時候,首先判斷這個服務物件是否已經存在:如果已經存在,則立即返回,否則調用他的一個虛的方法createService()來建立,並儲存建立的這個服務物件.隨意不同服務的ServiceFetcher實現了不同的建立對象的方法createService().這樣一來,就可以通過SYSTEM_SERVICE_MAP裡面各個服務的ServiceFetcher來擷取其對象了.

 

    /*package*/ static class ServiceFetcher {        int mContextCacheIndex = -1;        /**         * Main entrypoint; only override if you don't need caching.         */        public Object getService(ContextImpl ctx) {            ArrayList cache = ctx.mServiceCache;            Object service;            synchronized (cache) {                if (cache.size() == 0) {                    // Initialize the cache vector on first access.                    // At this point sNextPerContextServiceCacheIndex                    // is the number of potential services that are                    // cached per-Context.                    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {                        cache.add(null);                    }                } else {                    service = cache.get(mContextCacheIndex);                    if (service != null) {                        return service;                    }                }                service = createService(ctx);                cache.set(mContextCacheIndex, service);                return service;            }        }        /**         * Override this to create a new per-Context instance of the         * service.  getService() will handle locking and caching.         */        public Object createService(ContextImpl ctx) {            throw new RuntimeException("Not implemented");        }    }

( 3)SYSTEM_SERVICE_MAP的初始化.

 

在ContextImp中,有一段static的代碼塊,用於初始化所有服務的ServiceFetcher,並且加入SYSTEM_SERVICE_MAP裡面.

下面看看電源管理服務的初始化:

 

        registerService(POWER_SERVICE, new ServiceFetcher() {                public Object createService(ContextImpl ctx) {                    IBinder b = ServiceManager.getService(POWER_SERVICE);                    IPowerManager service = IPowerManager.Stub.asInterface(b);                    return new PowerManager(ctx.getOuterContext(),                            service, ctx.mMainThread.getHandler());                }});
registerService其實是一個static的方法,其主要工作就是:SYSTEM_SERVICE_MAP.put(serviceName, fetcher);

 

 

通過上面的分析,可以很好的瞭解原廠模式和單列模式的混合使用,這樣理解沒有問題嗎?說上面的設計模式為享元模式似乎更合適!當然,不夠我覺得不管上面設計模式其實都是一種名稱罷了!重要的是知道如何解決實際問題!其實我認為:享元模式就是等於原廠模式+單列模式+(或者還以有其他模式).其中要清楚的是,享元模式的重點在於:共用,不重複.其目的往往時為瞭解決:大量重複量級的對象使用.

 

 


 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.