Android系統(tǒng)服務(wù)是如何獲取的
Android獲取系統(tǒng)服務(wù)一般都需要用getSystemService指定系統(tǒng)服務(wù)名稱獲?。?/p>
val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
在實(shí)際開發(fā)中,當(dāng)我們需要編寫提供某一業(yè)務(wù)流程處理的Manager,通常會實(shí)現(xiàn)為單例。那么上面那行代碼背后發(fā)生了什么,為什么Android不使用單例模式呢?下面我們觀察Android是如何設(shè)計(jì)獲取系統(tǒng)服務(wù)的,它如何從應(yīng)用側(cè)到達(dá)系統(tǒng)側(cè)。
可以思考一下,不在每個服務(wù)中單獨(dú)使用單例的原因大概是因?yàn)锳ndroid提供的系統(tǒng)服務(wù)眾多,都使用getSystemService方法相當(dāng)于提供了統(tǒng)一的入口。同時因?yàn)榉椒▍?shù)中的服務(wù)名稱字符串,可以提供一個Map來統(tǒng)一存放各種服務(wù)實(shí)例,這與單例模式十分接近,相當(dāng)于統(tǒng)一管理各種單例的變種。那么事實(shí)是不是這樣呢?(下方源碼只保留關(guān)鍵代碼,API 30)
獲取系統(tǒng)服務(wù)源碼實(shí)現(xiàn)各種繼承或者持有Context的組件的getSystemService方法都會調(diào)用ContextImpl的同名方法:
//ContextImpl.java public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); }
SystemServiceRegistry一看就是統(tǒng)一注冊系統(tǒng)服務(wù)的地方:
//SystemServiceRegistry.java public static Object getSystemService(ContextImpl ctx, String name) { final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); final Object ret = fetcher.getService(ctx); return ret; }
這里我們確實(shí)發(fā)現(xiàn)了Map,可卻不是從String到系統(tǒng)服務(wù)的Map,SYSTEM_SERVICE_FETCHERS的類型為Map<String, ServiceFetcher<?>>。
//SystemServiceRegistry.java static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); }
這個SystemServiceRegistry中的內(nèi)部接口ServiceFetcher,看上去像是各種系統(tǒng)服務(wù)的工廠接口。我們看它的實(shí)現(xiàn)類:
//SystemServiceRegistry.java static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> { private final int mCacheIndex; CachedServiceFetcher() { mCacheIndex = sServiceCacheSize++; } @Override public final T getService(ContextImpl ctx) { final Object[] cache = ctx.mServiceCache; T ret = null; T service = (T) cache[mCacheIndex]; if (service != null) {ret = service; } else {service = createService(ctx);cache[mCacheIndex] = service;ret = service; } return ret; } public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; }
getService方法精簡了大量保證線程安全的同步措施,只保留了最核心的邏輯??梢钥吹搅碛幸粋€類型為Object[]的數(shù)組ctx.mServiceCache,getService從中用下標(biāo)mCacheIndex獲取系統(tǒng)服務(wù),如果服務(wù)為空則使用createService方法創(chuàng)建服務(wù)并放在數(shù)組中。可以說,這個ctx.mServiceCache數(shù)組起到了我們最初設(shè)想的從String到系統(tǒng)服務(wù)的Map的存放所有系統(tǒng)服務(wù)的作用。這個映射變?yōu)榱耍?/p>
假象的映射(從String到系統(tǒng)服務(wù)) <=> SYSTEM_SERVICE_FETCHERS映射(從String到ServiceFetcher) + ctx.mServiceCache數(shù)組(ServiceFetcher中的mCacheIndex下標(biāo)到系統(tǒng)服務(wù))
這個SYSTEM_SERVICE_FETCHERS映射在SystemServiceRegistry的靜態(tài)初始化快中被統(tǒng)一填充,同時提供了上方?jīng)]有實(shí)現(xiàn)的createService:
//SystemServiceRegistry.java static { registerService(Context.WINDOW_SERVICE, WindowManager.class,new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) {return new WindowManagerImpl(ctx); }}); } private static <T> void registerService(@NonNull String serviceName, @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) { SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher); }
SystemServiceRegistry類初始化時,ctx.mServiceCache系統(tǒng)服務(wù)數(shù)組還是空的,當(dāng)某一系統(tǒng)服務(wù)需要時,上方CachedServiceFetcher中g(shù)etService會調(diào)用createService創(chuàng)建服務(wù)并存放在特定mCacheIndex下標(biāo)中。
總結(jié)一下就是:在Android獲取系統(tǒng)服務(wù)的流程中,使用工廠模式創(chuàng)建系統(tǒng)服務(wù),使用Map管理工廠,使用數(shù)組管理系統(tǒng)服務(wù)實(shí)例。每種服務(wù)在每個ContextImpl中的數(shù)組中最多只有一個,且使用前不會提前創(chuàng)建,這點(diǎn)和單例的懶漢式是一致的。
真正的系統(tǒng)服務(wù)提供者我們知道Android Framework中系統(tǒng)服務(wù)是運(yùn)行在系統(tǒng)進(jìn)程中,需要通過Binder機(jī)制與應(yīng)用進(jìn)程通信,如果我們不考慮系統(tǒng)側(cè)實(shí)現(xiàn),上面拿到的類真的應(yīng)用側(cè)的Binder類么?其實(shí)并不全是,依舊查看工廠類中的工廠方法:
上面獲取到的服務(wù)類,有些類的確是系統(tǒng)側(cè)的系統(tǒng)服務(wù)對應(yīng)到應(yīng)用側(cè)的Binder類,比如AlarmManager://SystemServiceRegistry.java registerService(Context.ALARM_SERVICE, AlarmManager.class,new CachedServiceFetcher<AlarmManager>() { @Override public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);IAlarmManager service = IAlarmManager.Stub.asInterface(b);return new AlarmManager(service, ctx); }}); 有些則是對這些Binder類的直接封裝,比如ActivityManager:
//SystemServiceRegistry.javaregisterService(Context.ACTIVITY_SERVICE, ActivityManager.class,new CachedServiceFetcher<ActivityManager>() { @Override public ActivityManager createService(ContextImpl ctx) {return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }});
其中大量的方法使用getService與getTaskService進(jìn)行委托:
//ActivityManager.java public void killUid(int uid, String reason) { try { getService().killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid), reason); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public List<RunningTaskInfo> getRunningTasks(int maxNum) throws SecurityException { try { return getTaskService().getTasks(maxNum); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public static IActivityManager getService() { return IActivityManagerSingleton.get(); } private static IActivityTaskManager getTaskService() { return ActivityTaskManager.getService(); }
而getService與getTaskService都是單例方法,另外使用ServiceManager獲取真正的Binder類。
另外還有些系統(tǒng)服務(wù)為了便于使用,封裝得更加復(fù)雜,比如WindowManager:registerService(Context.WINDOW_SERVICE, WindowManager.class,new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) {return new WindowManagerImpl(ctx); }});
這里的各不同Context的WindowManagerImpl會統(tǒng)一調(diào)用到WindowManagerGlobal,而WindowManagerGlobal在addView時會創(chuàng)建ViewRootImpl,并將Binder類WindowSession傳遞給ViewRootImpl,由ViewRootImpl完成與WMS通信的工作。
以上實(shí)現(xiàn)了獲取系統(tǒng)服務(wù)時從應(yīng)用側(cè)到達(dá)系統(tǒng)側(cè)的過程。
以上就是Android系統(tǒng)服務(wù)是如何獲取的的詳細(xì)內(nèi)容,更多關(guān)于Android系統(tǒng)服務(wù)獲取的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. Python如何批量生成和調(diào)用變量2. ASP.Net Core對USB攝像頭進(jìn)行截圖3. ASP.NET MVC實(shí)現(xiàn)橫向展示購物車4. Python 中如何使用 virtualenv 管理虛擬環(huán)境5. Python獲取B站粉絲數(shù)的示例代碼6. Python基于requests實(shí)現(xiàn)模擬上傳文件7. python利用opencv實(shí)現(xiàn)顏色檢測8. windows服務(wù)器使用IIS時thinkphp搜索中文無效問題9. ASP.Net Core(C#)創(chuàng)建Web站點(diǎn)的實(shí)現(xiàn)10. 通過CSS數(shù)學(xué)函數(shù)實(shí)現(xiàn)動畫特效
