Android系統(tǒng)服務(wù)是如何獲取的
關(guān)于獲取系統(tǒng)服務(wù)的猜想
Android獲取系統(tǒng)服務(wù)一般都需要用getSystemService指定系統(tǒng)服務(wù)名稱(chēng)獲取:
val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
在實(shí)際開(kāi)發(fā)中,當(dāng)我們需要編寫(xiě)提供某一業(yè)務(wù)流程處理的Manager,通常會(huì)實(shí)現(xiàn)為單例。那么上面那行代碼背后發(fā)生了什么,為什么Android不使用單例模式呢?下面我們觀察Android是如何設(shè)計(jì)獲取系統(tǒng)服務(wù)的,它如何從應(yīng)用側(cè)到達(dá)系統(tǒng)側(cè)。
可以思考一下,不在每個(gè)服務(wù)中單獨(dú)使用單例的原因大概是因?yàn)锳ndroid提供的系統(tǒng)服務(wù)眾多,都使用getSystemService方法相當(dāng)于提供了統(tǒng)一的入口。同時(shí)因?yàn)榉椒▍?shù)中的服務(wù)名稱(chēng)字符串,可以提供一個(gè)Map來(lái)統(tǒng)一存放各種服務(wù)實(shí)例,這與單例模式十分接近,相當(dāng)于統(tǒng)一管理各種單例的變種。那么事實(shí)是不是這樣呢?(下方源碼只保留關(guān)鍵代碼,API 30)
獲取系統(tǒng)服務(wù)源碼實(shí)現(xiàn)
各種繼承或者持有Context的組件的getSystemService方法都會(huì)調(diào)用ContextImpl的同名方法:
//ContextImpl.java
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
SystemServiceRegistry一看就是統(tǒng)一注冊(cè)系統(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的類(lèi)型為Map<String, ServiceFetcher<?>>。
//SystemServiceRegistry.java
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
這個(gè)SystemServiceRegistry中的內(nèi)部接口ServiceFetcher,看上去像是各種系統(tǒng)服務(wù)的工廠接口。我們看它的實(shí)現(xiàn)類(lèi):
//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方法精簡(jiǎn)了大量保證線(xiàn)程安全的同步措施,只保留了最核心的邏輯??梢钥吹搅碛幸粋€(gè)類(lèi)型為Object[]的數(shù)組ctx.mServiceCache,getService從中用下標(biāo)mCacheIndex獲取系統(tǒng)服務(wù),如果服務(wù)為空則使用createService方法創(chuàng)建服務(wù)并放在數(shù)組中。可以說(shuō),這個(gè)ctx.mServiceCache數(shù)組起到了我們最初設(shè)想的從String到系統(tǒng)服務(wù)的Map的存放所有系統(tǒng)服務(wù)的作用。這個(gè)映射變?yōu)榱耍?/p>
假象的映射(從String到系統(tǒng)服務(wù)) <=> SYSTEM_SERVICE_FETCHERS映射(從String到ServiceFetcher)
+ ctx.mServiceCache數(shù)組(ServiceFetcher中的mCacheIndex下標(biāo)到系統(tǒng)服務(wù))
這個(gè)SYSTEM_SERVICE_FETCHERS映射在SystemServiceRegistry的靜態(tài)初始化快中被統(tǒng)一填充,同時(shí)提供了上方?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類(lèi)初始化時(shí),ctx.mServiceCache系統(tǒng)服務(wù)數(shù)組還是空的,當(dāng)某一系統(tǒng)服務(wù)需要時(shí),上方CachedServiceFetcher中g(shù)etService會(huì)調(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ù)在每個(gè)ContextImpl中的數(shù)組中最多只有一個(gè),且使用前不會(huì)提前創(chuàng)建,這點(diǎn)和單例的懶漢式是一致的。
真正的系統(tǒng)服務(wù)提供者
我們知道Android Framework中系統(tǒng)服務(wù)是運(yùn)行在系統(tǒng)進(jìn)程中,需要通過(guò)Binder機(jī)制與應(yīng)用進(jìn)程通信,如果我們不考慮系統(tǒng)側(cè)實(shí)現(xiàn),上面拿到的類(lèi)真的應(yīng)用側(cè)的Binder類(lèi)么?其實(shí)并不全是,依舊查看工廠類(lèi)中的工廠方法:
- 上面獲取到的服務(wù)類(lèi),有些類(lèi)的確是系統(tǒng)側(cè)的系統(tǒng)服務(wù)對(duì)應(yīng)到應(yīng)用側(cè)的Binder類(lèi),比如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);
}});
- 有些則是對(duì)這些Binder類(lèi)的直接封裝,比如ActivityManager:
//SystemServiceRegistry.java
registerService(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類(lèi)。
- 另外還有些系統(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會(huì)統(tǒng)一調(diào)用到WindowManagerGlobal,而WindowManagerGlobal在addView時(shí)會(huì)創(chuàng)建ViewRootImpl,并將Binder類(lèi)WindowSession傳遞給ViewRootImpl,由ViewRootImpl完成與WMS通信的工作。
以上實(shí)現(xiàn)了獲取系統(tǒng)服務(wù)時(shí)從應(yīng)用側(cè)到達(dá)系統(tǒng)側(cè)的過(guò)程。
以上就是Android系統(tǒng)服務(wù)是如何獲取的的詳細(xì)內(nèi)容,更多關(guān)于Android系統(tǒng)服務(wù)獲取的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android 多圖上傳后將圖片進(jìn)行九宮格展示的實(shí)例代碼
這篇文章主要介紹了Android 多圖上傳后將圖片進(jìn)行九宮格展示,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
Kotlin實(shí)現(xiàn)網(wǎng)絡(luò)圖片下載和保存功能
根據(jù)Android多線(xiàn)程和網(wǎng)絡(luò)編程的知識(shí)講解和案例使用,使用Handler消息機(jī)制實(shí)現(xiàn)網(wǎng)絡(luò)圖片下載,并且保存到模擬器中,強(qiáng)化對(duì)Android多線(xiàn)程編程、網(wǎng)絡(luò)編程和文件讀寫(xiě)的理解,這篇文章主要介紹了Kotlin實(shí)現(xiàn)網(wǎng)絡(luò)圖片下載和保存功能,需要的朋友可以參考下2023-02-02
Android系統(tǒng)進(jìn)程間通信Binder機(jī)制在應(yīng)用程序框架層的Java接口源代碼分析
本文主要介紹 Android系統(tǒng)進(jìn)程間通信Binder機(jī)制Java 接口源碼分析,這里詳細(xì)介紹了如何實(shí)現(xiàn)Binder 機(jī)制和Java接口直接的通信,有興趣的小伙伴可以參考下2016-08-08
Android?App跳轉(zhuǎn)微信小程序踩坑實(shí)戰(zhàn)
現(xiàn)在市面上很多的應(yīng)用都可以實(shí)現(xiàn)相互跳轉(zhuǎn),下面這篇文章主要給大家介紹了關(guān)于Android?App跳轉(zhuǎn)微信小程序踩坑的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
Android Flutter實(shí)現(xiàn)興趣標(biāo)簽選擇功能
我們?cè)谑状问褂脙?nèi)容類(lèi) App 的時(shí)候,不少都會(huì)讓我們選擇個(gè)人偏好,通過(guò)這些標(biāo)簽選擇可以預(yù)先知道用戶(hù)的偏好信息。我們本篇就來(lái)看看 Flutter 如何實(shí)現(xiàn)興趣標(biāo)簽的選擇,需要的可以參考一下2022-11-11
Android Studio 代理配置指南(小結(jié))
這篇文章主要介紹了Android Studio 代理配置指南(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
android獲取圖片尺寸的兩種方式及bitmap的縮放操作
這篇文章主要介紹了android獲取圖片尺寸的兩種方式及bitmap的縮放操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
提示信息控件AlertDialog對(duì)話(huà)框詳解
這篇文章主要為大家介紹了提示信息控件AlertDialog對(duì)話(huà)框的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
android 字體顏色選擇器(ColorPicker)介紹
本文將詳細(xì)介紹android 字體顏色選擇器(ColorPicker)需要了解更多的朋友可以參考下2012-11-11
Android基于OkHttp實(shí)現(xiàn)下載和上傳圖片
這篇文章主要為大家詳細(xì)介紹了Android基于OkHttp實(shí)現(xiàn)下載和上傳圖片功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11

