Android系统编程入门系列之加载服务Service

以前几篇文章简单梳理了在Android系统的四大组件之一,最主要的界面Activity中,使应用程序与用户进行交互响应的相关知识点,那对于应用程序中不须要与用户交互的逻辑,又要用到哪些内容呢?本文开始将介绍应用程序无需界面交互的内部交互相关知识点,首先从另一个四大组件之一的服务Service开始。html

清单文件一文的组件声明中,已经知道服务Service与界面Activity同样,都要在清单文件中注册声明。一样的,每一个注册声明的服务Service类向上追溯都必须继承自android.app.Service父类,所以服务Service也有本身的生命周期。android

生命周期

Service主要负责应用程序中不须要界面展现或交互的长时间操做,像是播放音乐,网络请求等都是能够在服务Service中完成的。与界面Activity的生命周期同样,在服务Service的声明周期内不容许执行耗时操做,因此,虽然服务Service中能够进行长时间操做,可是仍然须要将这部分耗时操做放入非Android系统主线程中。网络

(调用构造方法)对象实例化

首次启动新的服务Service时,系统会申请内存空间存储该服务Service的实例化对象。服务Service两种启动方式,其一与界面Activity同样须要借助意图Intent对象,调用上下文环境Context对象的startService(Intent service)启动。app

其二是进程间通讯时所用的方式,不只要借助意图Intent对象,还要使用实现android.content.ServiceConnection接口的对象,进而调用上下文环境Context对象的bindService(Intent service, ServiceConnection conn, int flags)方法,而参数三 flags 标记了启动该服务Service时所绑定的模式,一般使用Context.BIND_AUTO_CREATE标记会自动建立当前绑定的服务Service。除此以外,还能够按位或的形式追加其余标记,例如追加|Context.BIND_NOT_FOREGROUND标记当前绑定服务Service为较低优先级的后台服务,在手机息屏或高能耗时,系统会优先杀死低优先级的服务;而追加|Context.BIND_IMPORTANT标记能够提高绑定服务Service的优先级为前台服务,在手机息屏或高能耗时,只要当前应用程序存活,当前服务Service就不会被杀死;若是追加|Context.BIND_ABOVE_CLIENT标记当前绑定服务Service的优先级要高于当前应用程序,当手机息屏或高能耗时,系统可能会先杀死应用程序,可是当前服务Service仍然存活。google

Android系统为不一样进程间的通讯提供了一套AIDL语言规范,详情将在之后的文章中介绍,这里只需了解在实现ServiceConnection接口中,要重写两个方法,分别是在进程通讯接口与服务Service链接成功后回调的onServiceConnected(ComponentName name, IBinder service)方法,和链接断开以后回调的onServiceDisconnected(ComponentName name)方法。线程

上述两种启动方式,都会触发系统在当前应用程序的清单文件中查找对应注册过的服务Service,在找到以后,就会建立其实例化对象,若是在清单文件中没有找到对应的服务Service,将不会有任何错误或异常。设计

与启动未注册的服务Service不一样的是,当调用startActivity()系列方法启动一个没有在清单文件中注册过的界面Activity时,系统一般会抛出android.content.ActivityNotFoundException异常。code

(调用attachBaseContext(Context base))加载运行环境

因为Service也是android.content.ContentWrapper的子类,因此系统在建立服务Service的实例化对象后,也会优先对其加载上下文运行环境,将参数 base 做为当前应用程序的Context对象与该服务Service绑定。在该方法被调用以后的任意位置,就能够经过调用getBaseContext()等系列方法获取并使用当前服务Service所在的上下文环境了。htm

(调用onCreate())服务建立

在建立服务Service并加载运行环境以后,系统会优先调用该方法,表示当前服务已经完成建立。能够重写该方法执行一些服务内部使用的资源初始化操做。在执行完该方法以后,就标志着当前服务Service建立成功了,以后会一直处于运行状态,同时根据上述启动方式的不一样,调用不一样的生命周期方法。对象

(调用onStartCommand(Intent intent, int flags, int startId))服务启动

若是是经过上述启动方式一启动的服务Service,每调用一次startService(),系统都会调用一次该方法。
其中参数 intent 接收每次启动服务所传入的Intent意图。
参数 flags 标记当前服务屡次启动状态,通常默认是 0 ;当该服务Service被首次调用该方法且成功返回Service.START_REDELIVER_INTENT=3后,莫名被系统杀死,以后再次启动该服务时,标记参数则是 Service.START_FLAG_REDELIVERY=1 ;若是该服务Service被首次调用该方法并未返回结果,系统将会再次尝试调用该方法,标记参数则为 Service.START_FLAG_RETRY=2
参数 startId 做为系统惟一值,以此标记当前服务Service
最终返回指定的int类型,若是返回默认的Service.START_STICKY_COMPATIBILITY=0,当系统杀死该服务Service后,再次调用startService()将不会再被系统回调该方法;另外若是返回Service.START_STICKY=1,在系统杀死该服务Service后,再次调用startService()将会被系统从新建立实例化并回调该方法。

(调用onBind(Intent intent))服务绑定

若是是经过上述启动方式二启动的服务Service,在首次调用bindService()后,系统会调用该方法,而以后若是屡次调用bindService(),只有在当前服务Service已经执行完onUnbind()解绑的生命周期方法,并在解绑方法中返回 false 时,系统才会回调该方法。参数 intent 接收绑定服务所传入的Intent意图,最终返回android.os.IBinder接口的实现类对象。返回结果能够在bindService(Intent service, ServiceConnection conn, int flags)方法的参数二conn.onServiceConnected(ComponentName name, IBinder service)方法中接收,也就是其中的参数二IBinder类型的 service

服务解绑(调用onUnbind(Intent intent))

若是是经过上述启动方式二启动的服务Service,能够在bindService()绑定服务Service位置相对应的位置,调用unbindService()解绑服务Service。以后系统会回调该方法,一样的借助参数Intent意图实例来指定要解绑的指令信息。

服务重绑(调用onRebind(Intent intent))

若是是经过上述启动方式二启动的服务Service,若是当前服务Service已经执行完解绑生命周期,并在onUnbind()方法中返回 true 时,系统将会调用该方法以使用原有的IBinder对象从新绑定当前服务Service,所以该方法不须要返回值。其参数 intent 接收绑定服务所传入的Intent意图。最终返回值boolean类型,以标记当前服务再次被绑定时是否使用原有绑定过的IBinder对象。

服务销毁(调用onDestroy())

启动以后的服务Service会一直处于运行状态,直到系统可能因能耗过过而杀死低优先级的进程时,当前服务Service将会被动杀死,或者当前服务Service主动调用代码中止运行。与上述两种启动方式对应,服务Service也有两种中止方式
其一对应于startService()启动的服务,调用上下文环境Context对象的stopService(Intent service)方法中止运行,或者调用当前服务Service对象的stopSelf()方法也能够中止运行自身服务。
其二对应于bindService()绑定的服务,调用上下文环境Context对象的unbindService(ServiceConnection conn)方法解除绑定。因为绑定该服务的能够有多个ServiceCOnnection链接,因此必须每一个bindService()绑定服务的位置都对应调用unbindService()方法主动解绑,以防止出现内存泄漏或资源占用等误操做。

在服务Service全部绑定已解绑或主动中止运行后,系统最终会调用该方法,以后将销毁内存中建立的该服务Service实例化对象。所以能够重写该方法,对应于onCreate()中申请的初始化资源在该方法中释放掉。


服务Service的生命周期与界面Activity有些相似,这也保证了在其中能够执行无用户交互的操做,那么针对这种应用场景还须要怎么构建子线程操做呢?并且服务Service的设计还能够进行进程间通讯。具体又是如何编写代码搭建进程间的沟通桥梁呢?敬请期待后续文章。

相关文章
相关标签/搜索