当请求启动一个服务时,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一样的。 版权声明:本文为appdsn原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。