Service基础|青训营笔记

174 阅读5分钟

Service基础|青训营笔记

这是我参与[第四届青训营]笔记创作活动的第3天

前言

本文所写的是本人的个人见解,如有错误或者不恰当之处,欢迎私信我,加以改正!

本文将从什么是Service,service生命周期,两种service使用方式

1.什么是Service

Service是一个四大组件之一,可以在后台执行长时间运行的操作。它不提供用户界面。一旦启动,服务可能会继续运行一段时间,即使在用户切换到另一个应用程序之后也是如此。此外,组件可以绑定到服务以与其交互,甚至执行进程间通信 (IPC)

官方解释是围绕着service不是什么:

  • Service不是一个单独的进程。Service对象本身并不意味着它正在自己的进程中运行;除非另有指定,否则它将在与它所属的应用程序相同的进程中运行。
  • Service不是线程。它本身不是在主线程之外完成工作的手段(以避免应用程序无响应错误)

因此Service的主要作用有两个方面:

  1. 应用程序可以告诉系统它想要在后台执行的操作(即使用户不直接与应用程序交互)。这对应于对context.startService()的调用,该调用要求系统安排service的工作,直到service或其他人显式停止它为止。
  2. 应用程序向其他应用程序公开其某些功能的工具。这对应于对Context.bindService()的调用,它允许与service建立长期连接,以便与service进行交互。

2.Service的生命周期

了解Service之后,接下来就介绍一下service的生命周期⬇️

image.png 由上面的内容可以知道service的是有两种类型:

  1. StartService()启动service(启动后运行)
  2. BindService()启动service(需绑定后运行)

常用方法

onStartCommand()

startService()当另一个组件请求启动服务时,系统通过调用此方法来调用此方法。当这个方法执行时,服务就会启动并且可以无限期地在后台运行。如果您实现了这一点,您有责任在服务完成时通过调用stopSelf()或停止服务stopService()。如果您只想提供绑定,则不需要实现此方法。

onBind()

bindService()当另一个组件要与服务绑定时,系统会通过调用该方法来调用该方法。在此方法的实现中,您必须提供一个接口,客户端使用该接口通过返回一个IBinder. 您必须始终实现此方法;但是,如果您不想允许绑定,则应返回 null。

onCreate()

onStartCommand()系统在最初创建服务时(在调用或 之前)调用此方法来执行一次性设置过程 onBind()。如果服务已在运行,则不调用此方法。

onDestroy()

当服务不再使用并且正在被销毁时,系统会调用此方法。您的服务应该实现它以清理任何资源,例如线程、注册的侦听器或接收器。这是服务收到的最后一个调用。

3.Service使用方式

  1. StartService()启动service(启动后运行)

首次启动会创建一个service实例,根据其生命周期来看,依次调用onCreate()和onStartCommand()方法,此时Service进入运行状态,如果再次调用StartService启动service,将不再创建新的service对象,系统将直接调用前面已创建的service对象,调用其onStartCommand()方法,也因此可以说它不受调用者的生命周期限制,只要不调用stopService方法那么service就会一直运行。

接下来我们创建一个项目去测试一下service的生命周期吧,首先我们在activity中创建两个按钮,之后创建一个startService类去继承service就行,代码如下

 class StartService : Service() {
 ​
     private val TAG:String = "StartServiceLearn"
     //创建Service时调用
     override fun onCreate() {
         Log.d(TAG, "onCreate " + javaClass.simpleName)
         super.onCreate()
     }
     //销毁Service时调用
     override fun onDestroy() {
         Log.d(TAG, "onDestroy " + javaClass.simpleName)
         super.onDestroy()
     }
     //必须实现的一个方法,若为Startservice则返回为null就行
     override fun onBind(intent: Intent?): IBinder? {
         Log.d(TAG, "onBind " +javaClass.simpleName)
         return null
     }
     //接收intent
     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
         Log.d(TAG, "onStartCommand " + javaClass.simpleName)
         return super.onStartCommand(intent, flags, startId)
     }
     override fun onUnbind(intent: Intent?): Boolean {
         Log.d(TAG, "onUnbind: " + javaClass.simpleName)
         return super.onUnbind(intent)
     }
 ​
     override fun onRebind(intent: Intent?) {
         Log.d(TAG, "onRebind: "+ javaClass.simpleName)
         super.onRebind(intent)
     }
 }

运行情况如下

image-20220806205047658.png

如果我多次启动那又会怎样

image-20220806205134792.png 由上图可知多次启动并不会重新创建而是调用其onStartCommand方法,当我们点击停止服务(调用stopService方法)service就会被销毁。

那么大家可以多试试,思考一下如果我不停止startservice,直接返回上一个activity,此时服务的生命周期发生变化吗❓(其实并不会)

  1. BindService()启动service(需绑定后运行)

首次使用bindService绑定service对象是,系统会实例化一个service对象,并调用onCreate和onBind方法,然后调用者就利用binder和service进行交互,如果再次调用bindService去绑定service,系统不会创建新的service实例,也不再调用onBind,只会直接把binder对象传递给后来的进程,如果我们解除与服务的绑定只需调用unbindservice(),之后会调用onUnbind(),如果此时只绑定了多个进程,那么只有与所有的进程解除了绑定后,系统才会调用onDestory()方法来销毁service,或者所绑定的进程被销毁了,那么service对象也会终止

接下来,我们在原有项目的基础上,再创建一个BindService类,看看绑定服务的生命周期跟启动服务有什么区别,代码如下

 class BindService : Service() {
 ​
     private val binder:IBinder = MyBinder()
     private val TAG:String = "BindServiceLearn"
     //通信匿名类
     class MyBinder : Binder() {
         fun startBinder(){
             Log.d("BindServiceLearn", "MyBinder 中的 startBinder: ")
         }
         fun stopBinder(){
             Log.d("BindServiceLearn", "MyBinder 中的 stopBinder ")
         }
     }
     //绑定
     override fun onBind(intent: Intent?): IBinder? {
         Log.d(TAG, "onBind: "+ javaClass.simpleName)
         return binder
     }
     //创建Service时调用
     override fun onCreate() {
         Log.d(TAG, "onCreate: "+javaClass.simpleName)
         super.onCreate()
     }
     //销毁Service时调用
     override fun onDestroy() {
         Log.d(TAG, "onDestroy: " + javaClass.simpleName)
         super.onDestroy()
     }
     //解绑service时调用
     override fun onUnbind(intent: Intent?): Boolean {
         Log.d(TAG, "onUnbind: " + javaClass.simpleName)
         return super.onUnbind(intent)
     }
 ​
     //在BindService中不调用
     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
         Log.d(TAG, "onStartCommand: "+ javaClass.simpleName)
         return super.onStartCommand(intent, flags, startId)
     }
     override fun onRebind(intent: Intent?) {
         Log.d(TAG, "onRebind: " +  javaClass.simpleName)
         super.onRebind(intent)
     }
 }

运行情况如下

image-20220806212751389.png

如果我进行多次绑定又会如何:没有变化

image-20220806213020131.png

思考一下如果我选择返回上一个activity不进行解绑操作那会发生什么,直接帮我们调用onUnbind和onDestroy方法

image-20220806213434240.png

注意:每一个service都需要在Androidmanifest.xml中注册

  <service android:name=".StartService"/>

参考

服务概览|安卓开发者

浅谈 Android Service - 掘金 (juejin.cn)