文章目录
  1. 1. Service有两种状态,一种是启动状态,主要用于执行后台计算,另一种是绑定状态,主要用于与其他组件进行交互.这两种状态是可以共存的.
  • Service的启动过程
  • Service的绑定过程
  • 1
    2
    本文将介绍Service的工作过程,通过本文分析,你将会对Service的一些工作原理有更进一步的认识
    比如Service的启动过程和绑定过程.

    Service有两种状态,一种是启动状态,主要用于执行后台计算,另一种是绑定状态,主要用于与其他组件进行交互.这两种状态是可以共存的.

    Service的启动过程

    启动过程流程图

    img

    Service的启动过程从ContextWrapper的startService方法开始,如下所示

    1
    2
    3
    public ComponentName startService(Intent service) {
    return mBase.startService(service);
    }

    上面代码中的mBase的类型是ContextImpl,在Activity创建时会通过attach方法将ContextImpl对象关联起来,ContextWrapper的大部分操作都是mBase来实现的,这种模式叫桥接模式.
    在ContextImpl中,startService方法会调用startServiceCommon方法,而该方法会用过ActivityManagerNative.getDefault()对象来启动一个服务,也就是AMS,在AMS来启动服务的行为是一个远程过程调用,在AMS中会通过mServices这个对象完成后续的启动过程,mService对象 的类型是ActivityService,他是辅助AMS进行Service管理的类.包括启动、绑定、停止等.在它的startServiceLocked方法最后会调用startServiceInnerLocked方法,在该方法中并没有完成具体的启动工作,而是把后续的工作交给了bringUpServiceLocked来处理,在该方法中又调用了realStartServiceLocked方法,通过方法名来看这个方法应该是真正启动一个Service.

    在realStartServiceLocked方法中首先是通过app.thread的scheduleCreateService方法来调用Service的其他方法,比如onStartCommand,这两个过程均是进程通信.

    app.thread是IApplicationThread类型,它实际上是一个Bunder,他的具体实现是ApplicationThread和ApplicationThreadNative,而前者是继承与后者的,所以我们直接看ApplicationThread对Service启动过程的处理即可.这对应着它的scheduleCreateService方法,这个过程和Activity的启动过程是类似的,都是通过发送消息给Handler H来完成Service的最终完成.

    handlerCreateService方法主要做了这几件事

    1. 首先通过类加载器创建Service的实例
    2. 创建Application对象并调用其onCreate方法.创建过程只会有一次
    3. 创建ConTextImpl对象并通过Service的attach方法建立二者的关系.
    4. 最后调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中.

    到这里Service的启动过程已经分析完了,下面分析Service的绑定过程.

    Service的绑定过程

    绑定流程图
    img
    和Service启动过程一样,它的绑定过程也是从ContextWrapper开始的,如下所示.

    1
    2
    3
    4
    public boolean bindService(Intent service, ServiceConnection conn,
    int flags) {
    return mBase.bindService(service, conn, flags);
    }

    mBase同样是ContextImpl类型的对象,mBase的bindService方法最终会调用自己的bindServiceCommon方法

    bindServiceCommon方法主要完成如下两件事:

    首先将客户端的ServiceConnection对象转化为ServiceDispatcher.IServiceConnection对象.之所以不能使用ServiceConnection对象是因为服务的绑定可能是跨进成的,因此ServiceConnection对象必须借助与Binder才能让远程服务端回调自己的方法,而ServiceDispatcher的内部类IServiceConnection刚好充当了Binder这个角色.ServiceConnection起着连接SercviceConnection和InnerConnection的作用,这个过程由LoadedApk的getServiceDispatcher方法来完成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
    Context context, Handler handler, int flags) {
    synchronized (mServices) {
    LoadedApk.ServiceDispatcher sd = null;
    ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
    if (map != null) {
    sd = map.get(c);
    }
    if (sd == null) {
    sd = new ServiceDispatcher(c, context, handler, flags);
    if (map == null) {
    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
    mServices.put(context, map);
    }
    map.put(c, sd);
    } else {
    sd.validate(context, handler);
    }
    return sd.getIServiceConnection();
    }
    }

    在上面的代码中mServices是一个ArrayMap,它存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系,它的定义如下:

    1
    private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices

    接着bindServiceCommon方法会通过AMS完成Service的具体绑定过程.对应着AMS的binService方法,而该方法在调用bindServiceLocked方法,bindServiceLocked方法又会调用bringUpServiceLocked方法,bringUpServiceLocked又会调用realStartServiceLocked方法,realStartServiceLocked的执行逻辑和启动的逻辑类似,都是通过ApplicationThread来完成Service的创建并执行onCreate方法

    和启动Service不同的是,Service的绑定过程会调用app.thread的scheduleBindService方法,这个过程的实现在ActivityService的requestServiceBindingLocked方法,在该方法中调用了app.thread的scheduleBindService方法,他的内部都是通过Handler H中转的.

    在H内部接收到BIND_SERVICE这类消息时,会交给ActivityThread’的handleBind-Service方法来处理.在该方法中会根据Service的token取出Service对象,然后调用onBind方法.onBind方法会返回一个Binder对象给客户端使用.原则上此时已经属于绑定状态了,但是onBind方法是Service的方法,这个时候客户端并不知道已经成功连接了,所以还必须调用客户端的ServiceConnection中的onServiceConected,这个过程由ActivityManagerNative.getDefault()的publishService方法来完成的.他其实就是AMS.

    而AMS的publishService方法将具体的工作交给了ActivityServices类型的mServices对象来处理.在ActiveServices的publishServiceLocked方法核心代码只有一句

    1
    c.conn.connected(r.name, service);

    其中c的类型是ConnectionRecore.c.conn的类型是ServiceDispatcherInnerConnection.service就是Service的onBind方法返回的Binder对象. 从InnerConection的定义可以看出他的connected方法又调用了ServiceDispatcher的connected方法.

    对于Service的绑定过程来说,ServiceDisptcher的mActivityThread是一个Handler,他就是ActivityThread中的H,这样一来RunConnection就可以经过H的post方法从而运行在主线程中,因此客户端ServiceConnection中的方法是在主线程中回调的.

    客户端的onServiceConnected方法执行完毕之后,Service的绑定过程也就分析完成了.


    未经许可不得转载,转载请注明zilianliuxue的blog,本人保留所有版权。

    文章目录
    1. 1. Service有两种状态,一种是启动状态,主要用于执行后台计算,另一种是绑定状态,主要用于与其他组件进行交互.这两种状态是可以共存的.
  • Service的启动过程
  • Service的绑定过程