Service的两种启动
1. 同时存在两种启动
Snipaste_2018-08-03_11-01-42.png如果既startService又bindService(无论先后),那么点击stop是无法停止的(点击无反应)。
只有unbind解除绑定后才能进行销毁:
-
如果点击过stop,会unbind+destroy;
先startService后bindService
先bindService后startService - 如果没有点击过stop,此时只会unbind不会destroy。
总之,两种启动都存在的话,要stop是要先unbind的。
关于通过bindService启动的service,在unbindService后service是否继续运行的讨论
有三种情况:如果直接使用服务,则没有必要进行绑定,但是如果要使用服务里面的方法,则要进行绑定。具体的启动情况有下:
- 当启动时,单独调用bindService方法,在unbindService后,会执行service的onUnbind,在执行onDestroy方法。
- 当启动时,先调用startService,再调用bindService方法后,在unbindService后,会执行service的onUnbind,不会执行onDestroy方法。除非你在执行stopService。
- 先调用startService,在调用stopService,会执行service的onDestroy方法。
2. startService
已经知道多次以start方式启动service,只会执行一次onCreate(),会调用多次onStartCommand()。
多次startService,可以是多个Activity里start,多个intent。结果是onStartCommand()中的startId不同。
//连续启动Service
Intent intentOne = new Intent(this, TestOneService.class);
startService(intentOne);
Intent intentTwo = new Intent(this, TestOneService.class);
startService(intentTwo);
Intent intentThree = new Intent(this, TestOneService.class);
startService(intentThree);
3. bindService
bindService启动服务特点:
- bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
- client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
- bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁。
总结调用bindService之后发生的事情:
1.client执行bindService()
2.如果Service不存在,则Service执行onCreate(),onBind()
3.client实例ServiceConnection执行onServiceConnected()方法
总结调用unbindService之后发生的事情:
1.client执行unbindService()
2.client与Service解除绑定连接状态
3.Service检测是否还有其他client与其连接,如果没有Service执行onUnbind()和onDestroy()
4. 两种启动方式的区别
BindService和Started Service都是Service,有什么地方不一样呢:
-
Started Service中使用StartService()方法来进行方法的调用,调用者和服务之间没有联系,即使调用者退出了,服务依然在进行【onCreate()- >onStartCommand()->startService()->onDestroy()】,注意其中没有onStart(),主要是被onStartCommand()方法给取代了,onStart方法不推荐使用了。
-
BindService中使用bindService()方法来绑定服务,调用者和绑定者绑在一起,调用者一旦退出服务也就终止了【onCreate()->onBind()->onUnbind()->onDestroy()】。(如果调用者被销毁,service会销毁)
5. flag
下面重点关注下onStartCommand(Intent intent, int flags, int startId)方法。
其中参数flags默认情况下是0,对应的常量名为START_STICKY_COMPATIBILITY。startId是一个唯一的整型,用于表示此次Client执行startService(...)的请求请求标识,在多次startService(...)的情况下,呈现0,1,2....递增。另外,此函数具有一个int型的返回值,具体的可选值及含义如下:
-
START_NOT_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,即使系统内存足够可用,系统也不会尝试重新创建此Service。除非程序中Client明确再次调用startService(...)启动此Service。
-
START_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,当系统内存足够可用的情况下,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand(...)方法,但其中的Intent将是null,pendingintent除外。
-
START_REDELIVER_INTENT:与START_STICKY唯一不同的是,回调onStartCommand(...)方法时,其中的Intent将是非空,将是最后一次调用startService(...)中的intent。
-
START_STICKY_COMPATIBILITY:compatibility version of {@link #START_STICKY} that does not guarantee that {@link #onStartCommand} will be called again after being killed。此值一般不会使用,所以注意前面三种情形就好。
以上的描述中,“当Service因为内存不足而被系统kill后”一定要非常注意,因为此函数的返回值设定只是针对此种情况才有意义的,换言之,当人为的kill掉Service进程,此函数返回值无论怎么设定,接下来未来的某个时间内,即使系统内存足够可用,Service也不会重启。