Service是一種計算型元件,用於在後臺執行一系列的計算任務。由於工作在後臺,因此使用者是無法直接感知到它的存在。Service元件和Activity元件略有不同,Activity元件只有一種執行模式,即Activity處於啟動狀態,但是Service元件卻有兩種狀態:啟動狀態和繫結狀態。當Service元件處於啟動狀態時,這個時候Service內部可以做一些後臺計算,並且不需要和外界有直接的互動。
Service分為兩種工作狀態,一種是啟動狀態,主要用於執行後臺計算,另一張是繫結狀態,主要用於其他元件和Service的互動,需要注意的是Service的這兩種狀態是可以共存的,即Service既可以處於啟動狀態也可以同時處於繫結狀態。
Service的啟動過程
Service的啟動過程從ContextWrapper的startService開始。
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
這裡的mBase的型別是ContextImpl,其實說到這,就得說下Activity被建立時會通過attach方法將一個ContextImpl物件關聯起來,這也就是mBase。從ContextWrapper的實現可以看出,其中大部分操作都是通過mBase來實現的,在設計模式中這是一種典型的橋接模式。
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
從startServiceCommon方法中可以看出,是ActivityManagerNative.getDefault()這個方法的類啟動的,其實ActivityManagerNative.getDefault()就是AMS,是通過AMS來啟動服務的行為是一個遠端過程呼叫。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startService: " + service + " type=" + resolvedType);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
在上面的程式碼中,AMS會通過mServices這個物件來完成Service後續的啟動過程,mServices物件的型別是ActiveService,ActiveService是一個輔助AMS進行Service管理的類,包括Service的啟動、繫結和停止等。
最終是通過app.thread的scheduleCreateService方法來建立Service物件並呼叫onCreate,接著再通過sendServiceArgsLocked方法來呼叫Service的其他方法,比如onStartCommand,這兩個過程均是程式間通訊,到最後是通過ApplicationThread的scheduleCreateService方法來
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
是通過發訊息給Handler H,H會接收這個CREATE_SERVICE訊息並通過handleCreateService方法來完成Service的最終啟動。
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
handleCreateService主要完成了如下幾件事:
- 通過類載入器建立Service的例項
- 建立Application物件並呼叫其onCreate,當然Application的建立過程只會有一次。
- 接著建立ConTextImpl物件並通過Service的attach方法建立二者之間的關係。
- 最後呼叫onCreate方法,並將Service物件儲存到ActivityThreadd的一個列表中。
Service的繫結過程
和Service的啟動過程一樣,Service繫結過程也是從ContextWrapper開始的。
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
然後會呼叫bindServiceCommon方法,這個方法主要完成如下兩件事情:
- 首先將客戶端的ServiceConnection物件轉化為ServiceDispatcher.InnerConnection物件。
- 接著bindServiceCommon會通過AMS來完成Service的具體繫結過程,對應於AMS的bindService方法。
最終也是呼叫handleBindService來處理。
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
最後,以借用一張流程圖來說明:
閱讀擴充套件
源於對掌握的Android開發基礎點進行整理,羅列下已經總結的文章,從中可以看到技術積累的過程。
1,Android系統簡介
2,ProGuard程式碼混淆
3,講講Handler+Looper+MessageQueue關係
4,Android圖片載入庫理解
5,談談Android執行時許可權理解
6,EventBus初理解
7,Android 常見工具類
8,對於Fragment的一些理解
9,Android 四大元件之 " Activity "
10,Android 四大元件之" Service "
11,Android 四大元件之“ BroadcastReceiver "
12,Android 四大元件之" ContentProvider "
13,講講 Android 事件攔截機制
14,Android 動畫的理解
15,Android 生命週期和啟動模式
16,Android IPC 機制
17,View 的事件體系
18,View 的工作原理
19,理解 Window 和 WindowManager
20,Activity 啟動過程分析
21,Service 啟動過程分析
22,Android 效能優化
23,Android 訊息機制
24,Android Bitmap相關
25,Android 執行緒和執行緒池
26,Android 中的 Drawable 和動畫
27,RecylerView 中的裝飾者模式
28,Android 觸控事件機制
29,Android 事件機制應用
30,Cordova 框架的一些理解
31,有關 Android 外掛化思考
32,開發人員必備技能——單元測試