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

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值