文章目录
一、Service 的生命周期
Service 是安卓四大组件中与 Activity 最相似的组件,它们都代表可执行的程序,Service 与 Activity 的区别在于:Service 一致运行在后台,它没有用户界面,所以绝对不会到前台来。一旦 Service 被启动起来,它就与 Activity 一样拥有自己的生命周期。根据 Service 的启动方式不同,其生命周期如下:
- void onCreate():当 Service 第一次被创建时调用。
- void onDestroy():在 Service 被关闭前回调该方法,Service 需要实现该方法来清理任何资源,如线程,已注册的监听器,接收器等。
- IBinder onBind(intent : Intent):该方法是 Service 的子类必须实现的方法,该方法返回IBinder对象来提供一个接口,以便客户来与服务通信。
- boolean onUnbind():当 Service 上绑定的所有客户端都断开连接时将会回调该方法。
- void onStart(intent : Intent, startId: Int):客户端调用 startService(Intent) 方法启动该 Service 时会回调该方法(早期版本)。现在使用 void onStartCommand(intent: Intent, flags: Int, startId: Int)。
- void onRebind():当 Service 被客户端A用 startService() 方法启动,又被客户端B用 binderService() 的方式绑定,客户端B调用 onUnbind() 方法解除绑定,然后再调用 binderService() 方法再次绑定这个 Service 时,会调用 onRebind() 方法(需要 onUnbind() 方法返回 true)
二、配置 Service
配置 Service 的方法与配置 Activity 时一样:在 AndroidManifest.xml 文件中为 <application…/> 元素添加 <service…/> 子元素即可配置 Service。一般可指定以下几个属性:
- name:指定该 Service 的实现类的类名。
- exported:指定该 Service 是否允许被其他应用调用。如果配置该 Service 时指定了 <intent-filter…/> 子元素,则该属性默认为 true。
- permission:指定启动该 Service 所需要的权限。
- process:指定该 Service 所处的进程,该 Service 组件默认处于该应用程序所在的进程中。
在 AndroidManifest.xml 文件中 <application…/> 元素下配置 Service 的例子如下:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- 配置了三个 activity -->
<activity android:name=".FizzBuzzTest"></activity>
<activity android:name=".ColorTest" />
<!-- 指定该 activity 为应用程序的入口 -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 配置一个 Service 组件 -->
<service android:name=".FirstService"></service>
</application>
三、启动 Service 的两种方式
3.1 startService(intent: Intent)
直接启动或关闭 Service
// 创建启动 Service 的 intent
val intent = Intent(this, MyService::class.java)
// 启动指定的 Service
startService(intent)
// 停止指定的 Service
stopService(intent)
3.2 bindService(service: Intent, conn: ServiceConnection, flags: Int)
- service:该参数通过 Intent 指定要启动的 Service。
- conn:该参数是一个 ServiceConnection 对象,该对象用于监听访问者与 Service 之间的连接情况。当访问者与 Service 之间连接成功时将回调该 ServiceConnection 对象的 onServiceConnection(name: ComponentName, servicec: IBinder)方法;当 Service 所在的宿主进程由于异常中止或其他原因终止,导致该 Service 与访问者之间断开连接时回调该 ServiceConnection 对象的 onServiceDisconnected(ComponentName) 方法,当调用者主动通过 unBindService() 方法断开与 Service 的连接时,不会调用此方法。
- flags:指定绑定时是否自动创建 Service(如果 Service 还未创建)。该参数可指定为 0(不自动创建)或 BIND_AUTO_CREATE(自动创建)。
Service 的部分代码:
class BindService : Service(){
...
private val binder = MyBinder()
//通过继承 Binder 来实现 MyBinder 类
inner class MyBinder : Binder(){
...
}
//Service 被绑定时回调该方法
override fun onBind(intent : Intent): IBinder{
...
return binder
}
//Service 被创建时回调该方法
override fun onCreate(){
...
}
//Service 被断开连接时回调该方法
override fun onUnbind(intent: Intent): Boolean {
...
}
//Service 被关闭之前回调该方法
override fun onDestroy(){
...
}
}
Activity 的部分代码:
class MainActivity : Activity(){
...
// 保持所启动的 Service 的 IBinder 对象
private lateinit var binder: BindService.MyBinder
// 定义一个 ServiceConnection 对象
private val conn = object : ServiceConnection{
// 当 Activity 与 Service 连接成功时回调该方法
override fun onServiceConnected(name: ComponentName, service: IBinder){
...
// 获取 Service 的 onBind 方法所返回的 MyBinder 对象
binder = service as BinderService.MyBinder
}
// 当 Activity 与 Service 断开连接时回调该方法
override fun onServiceDisconnected(name: ComponentName){
}
}
override fun onCreate(savedInstanceState: Bundle?){
...
// 创建启动 Service 的 intent
val intent = Intent(this, BindService::class.java)
button1.setOnClickListener{
// 绑定指定的 Service
bindService(intent, conn, Service.BIND_AUTO_CREATE)
}
button2.setOnClickListener{
// 解除绑定 Service
unbindService(conn)
}
...
}
...
}
四、IntentService
普通的 Service 存在以下两个问题:
- Service 不会启动一个单独的进程,Service 与他所在的应用位于同一个进程中。
- Service 不是一条新的线程,因此不应该在 Service 中直接处理耗时任务,否则可能引发 ANR 异常。
IntentService 刚好可以解决这两个问题:IntentService 将会使用队列来管理请求 Intent,每当客户端代码通过 Intent 请求启动 IntentService 时,IntentService 会将该 Intent 加入队列中,然后开启一条新的 worker 线程来处理该 Intent。对于异步的 startService() 请求,IntentService 会按次序依次处理队列中的 Intent,该线程保证同一时刻只处理一个 Intent。由于 IntentService 使用新的 worker 线程处理 Intent 请求,因此 IntentService 不会阻塞主线程,所以 IntentService 自己就可以处理耗时任务。IntentService 的特征如下:
- IntentService 会创建单独的 worker 线程来处理所有的 Intent 请求。
- IntentService 会创建单独的 worker 线程来处理 onHandleIntent() 方法实现的代码,因此开发者无须处理多线程问题。
- 当所有请求处理完成后,IntentService 会自动停止,因此开发者无须调用 stopSelf() 方法来停止该 Service。
- 为 Service 的 onBind() 方法提供了默认实现,默认实现的 onBInd() 方法返回 null。
- 为 Service 的 onStartCommand() 方法提供了默认实现,该实现会将请求 Intent 添加到队列中。
MyIntentService 的代码如下:
class MyIntentService : IntentService("MyIntentService"){
// IntentService 会使用单独的线程来执行该方法的代码
override fun onHandleIntent(intent: Intent?){
...
}
}