startService启动流程---Service在App进程但未启动

Service启动流程(startService)的最后,分析了在调用startService时可能存在的三种情况,本文分析第二种情况—Service与App在同一个进程,但未启动。

Service启动流程(startService)最后已经说明,在这种情况下,系统会执行realStartServiceLocked函数。

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app) throws RemoteException {
    ......
    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

    app.services.add(r);
    bumpServiceExecutingLocked(r, "create");
    updateLruProcessLocked(app, true, true);

    boolean created = false;
    try {
        ......
        //跨进程去执行Service实例的创建
        app.thread.scheduleCreateService(r, r.serviceInfo,
                compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
        r.postNotification();
        created = true;
    } finally {
        if (!created) {
            app.services.remove(r);
            scheduleServiceRestartLocked(r, false);
        }
    }

    ......
    //Service创建完成后,执行onStartCommand函数
    sendServiceArgsLocked(r, true);
}  

函数的逻辑还是比较清晰的,完成的工作主要有两个:

  • 创建Service实例
  • 执行onStartCommand方法

接下来就来看下这两个任务时如何完成的。

创建Service实例是一个Binder跨进程调用,Binder细节就不分析,直接进入ActivityThread查看scheduleCreateService的实现

public final void scheduleCreateService(IBinder token,
            ServiceInfo info, CompatibilityInfo compatInfo) {
        CreateServiceData s = new CreateServiceData();
        s.token = token;
        s.info = info;
        s.compatInfo = compatInfo;

        queueOrSendMessage(H.CREATE_SERVICE, s);
    }  

好吧,queueOrSendMessage这个函数我们在ActivityThread中已经看到过很多次调用很多次了,我们直接进入到真正执行创建Service实例的函数queueOrSendMessage

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.
    ......
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        //反射创建Service实例
        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 {
        ......

        ContextImpl context = new ContextImpl();
        context.init(packageInfo, null, this);

        Application app = packageInfo.makeApplication(false, mInstrumentation);
        context.setOuterContext(service);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());
         //执行Service onCreate方法
        service.onCreate();
        mServices.put(data.token, service);
        try {
            //通知ActivityManagerService实例创建完成
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, 0, 0, 0);
        } catch (RemoteException e) {
            // nothing to do.
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
}

函数的代码不短也不长,还是比较好理解的。首先获取Service的信息,然后调用反射创建Service实例(想想Activity实例的创建,是不是也是反射?),创建完实例后就会去执行attach方法,执行完attach方法后就会去执行onCreate方法(想想Activity,是不是也是先执行attach在执行onCreate?),执行完onCreate方法后,通知ActivityManagerService。

执行完Service实例的创建,接下来执行onStartCommand的流程就是 startService启动流程—Service已经启动中描述的流程,我就不再分析了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值