Context完全解析(四)Service的Context创建过程

xiaoxiao2021-02-28  12

 当请求启动一个服务时,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一样的。

转载请注明原文地址: https://www.6miu.com/read-2500112.html

最新回复(0)