Android 四大组件之Service知识总结

一、Service 的生命周期

Service 是安卓四大组件中与 Activity 最相似的组件,它们都代表可执行的程序,Service 与 Activity 的区别在于:Service 一致运行在后台,它没有用户界面,所以绝对不会到前台来。一旦 Service 被启动起来,它就与 Activity 一样拥有自己的生命周期。根据 Service 的启动方式不同,其生命周期如下:
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?){
    
    
		...
	}
}

猜你喜欢

转载自blog.csdn.net/qingyunhuohuo1/article/details/109474683