【Android面试-Android-V02】组件Service

52 阅读3分钟

Service

1. onStartCommand 返回值(一种保活)

当 Android 面临内存匮乏的时候,可能会毁掉你当前运行的 Service,然后待 内存充足的时候可以重新创建 Service,Service 被 Android 系统强制􏰗毁并再次 重建的行为依赖于 Service 中 onStartCommand 方法的返回值

  • START_NOT_STICKY,表示当 Service 运行的进程被 Android 系统 强制杀掉之后,不会重新创建该 Service,
  • START_STICKY,表示 Service 运行的进程被 Android 系统强制杀掉 之后,Android 系统会尝 试再次重新创建该 Service,并执行 onStartCommand 回调方法,但是 onStartCommand 回调方法的 Intent 参数为 null,
  • START_REDELIVER_INTENT 如果返回 START_REDELIVER_INTENT,表示 Service 运行的进程被 Android 系统强制杀掉之后,Android 系统会将再次重新创建该 Service,并执行 onStartCommand 回调方法,但是不同的是, Android 系统会创建并再次传入intent到重新创建后的 Service 的 onStartCommand 方法中。

2.IntentService

IntentService原理:

继承Service,内部封装了HandlerThread和Handler,可以执行耗时任务,同时因为它是一个服务,优先级比普通线程高很多,所以更适合执行一些高优先级的后台任务,HandlerThread底层通过Looper消息队列实现的,所以它是顺序的执行每一个任务。可以通过Intent的方式开启IntentService,IntentService通过handler将每一个intent加入HandlerThread子线程中的消息队列,通过looper按顺序一个个的取出并执行,执行完成后自动结束自己,不需要开发者手动关闭

  public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
​
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    
    
      private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
​
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
    
    

HandlerThread

HandlerThread = MessageQueue + Looper + Handler

继承自Thread,start开启线程后,会在其run方法中会通过Looper创建消息队列并开启消息循环,这个消息队列运行在子线程中,所以可以将HandlerThread中的Looper实例传递给一个Handler,从而保证这个Handler的handleMessage方法运行在子线程中,Android中使用HandlerThread的一个场景就是IntentService

 int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;
​
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

4.Service 的启动过程

service生命周期

bind方式启动

生命周期onCreate() -> onBind() -> onUnbind() -> onDestory()

bindService启动流程
  • ContextImpl.bindService()
  • ContextImpl.bindServiceCommon()
  • LoadApk.getServiceDispatcher()
  • AMS.bindService()
  • ActiveServices.bindServiceLocked()
  • ActiveServices.realStartServiceLocked
  • app.thread.scheduleCreateService
  • ActiveServices.requestServiceBindingsLocked
  • ActiveServices.sendServiceArgsLocked

bindService 的流程核心就是把 ServiceConnection 对象传递给 Activity 组件,在应用程序进程会执行 handleCreateService 和 handleBindService,前者就是 startService 的流程,后者即是多出来的 bind 流程。

在 ContextImpl 的 bindService 中,会首先把 ServiceConnection 通过 getServiceDispatcher 调用转化成一个 IServiceConnection 接口,这个 IServiceConnection 是一个 Binder 对象,所以就可以跨进程传递给 Activity 了。然后就是获取 AMS 的代理对象,去执行 bindService 调用。这个方法会传入 AppplicationThread、ActivityToken 以及 Intent。在 AMS 成功将 Service 组件启动起来之后,就会把这个 Binder 对象封装成一个消息,发送给 Activity 组件所运行的应用程序的主线程消息队列中,最后在分发给 Activity 组件内部的成员变量 ServiceConnection 的 onServiceConnected 来处理。Activity 组件获得了 Service 组件的访问接口之后,就可以调用其相关服务了。

非bind启动

context.startService() ->onCreate()- >onStart()->Service running-->( 如 果 调 用 context.stopService() )->onDestroy() ->Service shut down

  • ContextImpl 的 startService通过ActivityManagerNative binder调用 AMS
  • AMS中startServiceLocked,查询是否有intent对应的ServiceRecord ,如果不存在则通过PKMS查询
  • 调用 bringUpServiceLocked 判断该 Service 所在进程是否存在,然后realStartServiceLocked启动service
  • ActivityThread中 handleCreateService,调用 Service 的 attach 和 onCreate 函数
startService启动流程
  • ContextImpl.startService(Intent service)
  • ContextImpl.startServiceCommon()
  • AMS.startService()
  • ActiveServices.startServiceLocked()
  • ActiveServices.startServiceInnerLocked()
  • ActiveServices.bringUpServiceLocked()
  • ActiveServices.realStartServiceLocked()
  • ActiveServices.publishServiceLocked()

6.多次调用bindService(),为什么onBind()只执行一次?

blog.csdn.net/u013553529/…