Service:服务
Service是Android系统的核心组件之一!它是由Android系统进行管理和维护的!
Service是系统组件,所以,必须注册!而且,如果没有注册,并不会报错!!!
当进程中存在正在执行的Service时,整个进程将被列为“服务进程”,此时进程的优先级将高于“后台进程”和“空进程”,则可以使得进程不是那么容易被系统清理!
基于以上原则,如果需要执行某些耗时操作,则应该使用Service!所以,Service是适合用于执行耗时操作的!
尽管Service适合用于执行耗时操作,但是,Service是运行在主线程的!所以,需要在Service中开启子线程去执行耗时操作!
Service是与界面无关的,即:Service不存在界面,也不可以直接操作Activity中的控件!
Service是单例(实例唯一)的!
Service是一种适合在后台执行耗时操作的组件,只是它运行在主线程,所以需要开子线程来执行耗时操作!
启动模式的Service的生命周期
- onCreate() -> 当Service被创建时,该方法只会被回调一次,该方法适合用于编写初始化相关的代码
- onStartCommand() -> 当Service每次被启动时都会被回调一次
- onDestroy() -> 当Service被销毁时,该方法只会被回调一次,该方法适合用于编写释放资源相关的代码
激活Service
激活Service可以有“启动”和“绑定”这2种操作模式!
启动与停止Service
- 在Context或其子孙类中(例如在Activity中,或在Service中)调用startService(Intent)方法可以启动Service
- 在Context或其子孙类中(例如在Activity中,或在Service中)调用stopService(Intent)方法可以停止Service
- 在Service内调用stopSelf()方法可以停止自身Service
Service的粘性
Service的粘性表现为当Service被意外终止时,会自动重新启动!
Service的粘性是由onStartCommand()方法的返回值决定的,可使用的返回值常量有:
- Service.START_STICKY -> 粘性的
- Service.START_NOT_STICKY -> 非粘性的
- Service.START_STICKY_COMPATIBILITY -> 兼容模式的粘性的
- Service.START_REDELIVER_INTENT -> 当Service自动重启时会得到此前使用的Intent
当需要Service不是粘性时,onStartCommand()方法应该返回START_NOT_STICKY;当需要Service是粘性的,且需要重新得到Intent对象时,应该返回START_REDELIVER_INTENT;当需要Service是粘性的,却不需要重新得到Intent对象时,应该返回父类的方法的返回值!
绑定Service:组件间通信
绑定Service的操作相对启动Service更加繁琐,且绑定的Service没有“粘性”的概念!但是,它可以实现Activity向Service的通信,表现为Activity可以调用Service中的方法!
绑定流程
以WorkService类为例:
1. 自定义类WorkService,继承自android.app.Service
public class WorkService extends Service
2.在AndroidManifest.xml中注册Service
<service android:name="cn.tedu.bind_service.WorkService"></service>
3.[IMusicPlayer] 自定义接口IMusicPlayer,并在接口中声明那些由Activity调用,却由Service实现功能的抽象方法
4.[WorkService] 自定义内部类InnerBinder,继承自android.os.Binder,并实现IMusicPlayer接口,重写接口中的抽象方法
public class InnerBinder extends Binder
5.[WorkService] 在onBind()方法中,创建InnerBinder的对象,并作为该方法的返回值
@Override
public IBinder onBind(Intent intent) {
InnerBinder binder = new InnerBinder();
return binder;
}
6.[MainActivity] 自定义内部类InnerServiceConnection,实现ServiceConnection接口,并添加抽象方法
private class InnerServiceConnection implements ServiceConnection
7.[MainActivity] 当需要绑定时,调用bindService()方法实现绑定,该方法的第1个参数是Intent对象,用于指定被激活的Service组件,第2个参数是ServiceConnection对象,使用InnerServiceConnection对象,注意:InnerServiceConnection对象应该声明为全局变量,第3个参数是int类型的标记,使用Context.BIND_AUTO_CREATE
Intent service = new Intent(this, WorkService.class);
ServiceConnection conn = new InnerServiceConnection();
int flags = Context.BIND_AUTO_CREATE;
bindService(service, conn, flags);
8.[MainActivity] 声明全局变量IMusicPlayer player,在InnerServiceConnection的onServiceConntected()方法中,将参数IBinder service强制转换并赋值给player
9.[MainActivity] 当需要调用那些由Service实现的方法时,直接调用player对象的相关方法即可
10.[MainActivity] 最晚在onDestroy()中,调用unbindService(ServiceConnection conn)方法解绑Service
绑定Service的生命周期
- onCreate() -> 当第1次绑定时,创建Service时回调的方法,该方法只会被回调一次
- onBind() -> 当Activity绑定Service时调用的方法,该方法只会被回调一次
- onDestroy() -> 当Activity解除与Service的绑定时会被回调的方法,该方法只会被回调一次
【仅了解】绑定Service时一般不会被回调的方法
- onRebind() -> 当重新绑定Service时回调的方法,由于反复绑定是无效的,所以反复绑定并不会导致该方法被回调,但是,一旦解除绑定,Service将再销毁,再次绑定时会重新创建Service的对象以实现绑定,那么,再次绑定的Service对象与此前的并不是同一个对象,也不属于重新绑定!仅当Activity与某个Service对象解除绑定了以后,再次绑定到同一个Service对象,才会导致该方法回调!这样的现象仅仅只会出现在先使用startService()激活了Service组件,然后再调用bindService()实现绑定,由于Service是单例的,所以,即使使用了2种方式激活Service,也只会有1个Service对象,并且,以startService()方式激活的Service组件必须只能通过stopService()或在Service内部使用stopSelf()才会销毁,即当解除绑定时,该Service并不会被销毁,这样才会出现“重新绑定”!
- onServiceDisconnected() -> 该方法仅当Activity与Service的绑定意外断开时被会回调的方法!