当请求启动一个服务时,ActivityManagerService
首先会通过IPC调用到ActivityThread的scheduleCreateService()方法中,该方
法的参数中有一个
是Servicelnfo类参数,它是实现了 一 个Parcelable接口的数据类,该对象由
AmS创建,并通过
IPC传递到
ActivityThread
内部。
在scheduleCreateService()方法中,会使用这些参数构造 一 个CreateServiceData的数据对象,
ActivityThread
会为其所包含的每 一 个Service创建该数据对象,并通过这些对象来管理Service,
接着,会执行handleCreateService()方法。
public final class ActivityThread {
......
private void handleCreateService(CreateServiceData data) {
......
(1)创建Service实例
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) {
......
}
try {
(2)创建Service的Context
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
(3)创建Application实例
Application app = packageInfo.makeApplication(false, mInstrumentation);
(4)初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
(5)保存Service实例
mServices.put(data.token, service);
......
} catch (Exception e) {
......
}
}
......
}
我们可以将这个方法中的逻辑分为五大部分,首先通过反射来实例化一个Service对象,这和上面创建Activity实例是一样的,默认构造方法什么也不做,Service实例的初始化工作也在attach方法中。第二步:接着调用ContextImpl类的createAppContext静态方法来创建一个Service的ContextImpl实例对象,随后
通过这个Contextlmpl 类型实例context调用
setOuterContext()方法把service对象赋值给Contextlmpl的mOuterContext变量,这样ContextImpl对象就持有Service对象,可以调用Service中的方法和变量。
第三步:接着会创建
Application实例对象,由于进程启动的时候就已经创建了Application,这里会直接返回这个Application对象
。第四步:等Service实例对象和Application对象创建完成后,接着会调用Service对象的attach方法来初始化这个Service实例,
attach方法内部会调用其父类ContextWrapper中的attachBaseContext(context)方法,并且将Contextlmpl类实例作为参数传入,保存在其父类ContextWrap的mBase实例变量中,这样Service中就持有了Contextlmpl类实例,这个和初始化Activity一样的。
初始化完Service后,会调用其
onCreate方法,用户可在在这个方法里做自己的初始化工作
。最后,会将这个Service对象保存在
ActivityThread类中的一个数组实例变量中。
class ContextImpl extends Context {
......
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
null);
context.setResources(packageInfo.getResources());
return context;
}
......
}
createAppContext()方法需要两个参数,一个是
LoadApk类型的对象,另一个是 ActivityThread类型对象,接着
就通过new创建
一 个Contextlmpl对象, 然后返回。
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
......
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
attachBaseContext(context);
mThread = thread; // NOTE: unused - remove?
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
}
......
}
Service对象的
attach方法主要用来初始化一些变量,其内部会调用其父类ContextWrapper中的attachBaseContext(context)方法,并且将Contextlmpl类实例作为参数传入,保存在其父类ContextWrap的mBase实例变量中,这样Service中就持有了Contextlmpl类实例,这个和初始化Activity一样的。