Service、IntentService
IntentService
是service的子类,他会创建默认的工作线程,同时创建工作队列,逐一完成所有启动请求,不必担心多线程问题,onHandleIntent()处理启动任务。在处理完所有请求后会自动关闭服务。
在8.0已经弃用,用WorkManager或JobIntentService,它使用作业而不是服务。所以Android8.0及以上JobIntentService和JobService做的事情是相同的,都继承于service,都是等着JobScheduler分配任务来执行。不同点在于,JobService使用的handler使用的是主线程的Looper,因此需要在onStartJob()中手动创建AsyncTask去执行耗时任务,而JobIntentService则帮我们处理这一过程,使用它只需要写需要做的任务逻辑即可,不用关心卡住主线程的问题。
Service
面试语:
service是四大组件之一,通常在后台运行,默认情况下运行在主线程之中,但是也可以另行指定在其他进程中去运行,他不会自行创建线程,也不会独立在进程中运行。
service分为前台服务和后台服务两种,后台服务是没有用户可交互界面的。例如网易云音乐在切换至后台后,通知栏会显示音乐播放的服务通知,这属于前台服务,这种服务及时在内存紧张的情况下系统也不会杀死该服务,优先级比较高。但是在9.0及以后的系统中必须申请权限才可以使用。后台服务是没有可见界面的,在Android8.0及以上应用变为后台为了保证前台应用的正常运行,会对后台服务作出限制。在应用进入后台后,会有一个几分钟的缓冲时间后台服务可以正常工作,当时间结束后系统会默认该应用处于空闲状态从而停止后台服务就像我们自己调用了stopSlef()。通常可以通过JobScheduler(工作计划来解决这些问题,但是在Android10.0后也会对此作出限制)来完成,但是他会尽可能的在时间允许范围内做任务的推迟。
service可以通过其他组件启动,比如Activity、广播。如果服务将执行任何耗时操作,则应通过在服务内创建新线程来完成这项工作。通过使用单独的线程,可以降低发生“应用无响应”(ANR) 错误的风险,而应用的主线程仍可继续专注于运行用户与 Activity 之间的交互。
服务和线程:
服务用在及时应用没有在前台与用户进行交互也要运行的时候,如果仅仅是想在进行交互的时候做一些别的操作应该通过线程去实现
Intent:
通过显式Intent来启动服务使,用隐式 Intent 启动服务存在安全隐患,因为您无法确定哪些服务会响应 Intent,而用户也无法看到哪些服务已启动。从 Android 5.0(API 级别 21)开始,如果使用隐式 Intent 调用,则系统会抛出异常。
生命周期:
onCreate():
首次创建服务时,系统将调用此方法。如果服务已在运行,则不会调用此方法,该方法只调用一次,重复启动不会调用。
- 服务在没有启动的情况下直接绑定会运行OnCreate()和OnBind(),之后多次绑定不会再有方法调用,当绑定后再去启动服务只会运行onStartCommand()并不会再执行onCreate()和OnBind()。
onStartCommand():
代替已经过时的onStart()方法。
当另一个组件通过调用startService()请求启动服务时,系统将调用此方法。在此方法中会接收Intent。如果服务没有实现该方法,只做了绑定,服务只会在被其他组件绑定后运行,当所有绑定被取消后系统会将其销毁。
onDestroy():
当服务不再使用且将被销毁时,系统将调用此方法,在这个方法中做资源回收,如监听器、线程等。
onBind():
当另一个组件通过调用bindService()与服务绑定时,系统将调用此方法。
onUnbind():
当另一个组件通过调用unbindService()与服务解绑时,系统将调用此方法。
onRebind():
当旧的组件与服务解绑后,另一个新的组件与服务绑定,onUnbind()返回true时,系统将调用此方法。
在Service的生命周期里,常用的方法有:
手动调用的方法:
startService() 启动服务
stopService() 关闭服务
bindService() 绑定服务
unbindService() 解绑服务
自动调用的方法:
onCreat() 创建服务,只会在第一次启动时调用
onStartCommand() 开始服务,会在此方法中接收Intent
onDestroy() 销毁服务
onBind() 绑定服务
onUnbind() 解绑服务
- 生命周期调用
1)启动Service服务
单次:startService() —> onCreate() —> onStartCommand()
多次:startService() —> onCreate() —> onStartCommand() —> onStartCommand()
2)停止Service服务
stopService() —> onDestroy()
3)绑定Service服务
bindService() —> onCreate() —> onBind()
4)解绑Service服务
unbindService() —> onUnbind() —> onDestroy()
5)启动绑定Service服务
startService() —> onCreate() —> onStartCommand() —> bindService() —> onBind()
6)解绑停止Service服务
unbindService() —> onUnbind() —> stopService() —> onDestroy()
7)解绑绑定Service服务
unbindService() —> onUnbind(ture) —> bindService() —> onRebind()
- 服务可以通过bindService()直接启动,不需要先启动再绑定。
- 服务多次被绑定只会执行一次。
- 服务不能在未绑定的情况下执行解绑或者多次解绑,会报IllegalArgumentException异常。bindService有boolean返回。
- 服务通过绑定启动后通过stopService()无法关闭服务或者解绑服务,对于绑定过的服务需要解绑才能关闭服务。