顾所周知,Service是Android的四大组件之一,那么我们在什么场景下回用到Service呢?一个是用于长期执行某些操作,并且甚至与UI(主)线程没有交互后台运行。比如启动app直接去网络下载文件或者播放音乐,二个是跨进程间通信,比如appA程序中Service被appB中程序调用。
需要注意一点:Service默认时运行在它所在的宿主进程的主进程中,也就是说如果我们在Service中做耗时操作,UI(主)线程会卡死,出现ANR程序无响应现象。为防止这种情况发生,我们一般都会在Service中新创建一个Thread线程来处理一些耗时操作,这样就不会阻塞主线程。所以Service不是另一个独立的进程,Service自己本身不会开辟一个新的进程,除非手动来设置。默认情况下,Service是运行在本运用程序所属的进程中。
启动Service的方法有两种:startService()和bindService(),其实这两个方法也有它们的应用场景。如果是运行在后台的Service,不与UI(主)线程做交互的,我们一般用startService()。如果是两个不同的进程间通信,或者是程序中Service的方法是Public,我们一般用bindService()。
停止Service的方法也有两种:外部调用stopService(),或者内部调用stopSelf()。
onCreate():如果多次执行startService()方法启动Service,Service的onCreate()方法只会在第一次创建Service的时候调用一次,之后均不会再次调用。所以我们可以在onCreate()方法中完成一些Service初始化相关的操作。
onStartCommand():如果多次执行了startService()方法,那么Service的onStartCommand()方法也会相应的多次调用。onStartCommand()方法很重要,我们在该方法中根据传入的Intent参数进行实际的操作,比如会在此处创建一个线程用于下载数据或播放音乐等。在onStartCommand()方法中,因为starId是唯一的,startId默认从1开始,如果Service已经创建了,多次去调用startService来启动Service,则startId呈递增的形式,每次都会加1。
onBind():Service中的onBind()方法是个抽象方法,所以Service类本身就是一个抽象类,也就是说onBind()方法必须要重写,即使用不到。通过startService使用Service时,我们在重写onBind方法时,只需要将其返回值设为null即可。onBind()方法主要是用于bindService()方法调用Service时才使用到。
onDestory():Service销毁时回调函数。
重点要说的就是onStartCommand()方法的返回值
常有的返回值有:START_NOT_STICKY、START_SICKY和START_REDELIVER_INTENT,这三个都是静态常量值。
START_NOT_STICKY:表示当Service运行的进程被Android系统强制杀掉之后,不会重新创建该Service,如果想重新实例化该Service,就必须重新调用startService来启动。
使用场景:表示当Service在执行工作中被中断几次无关紧要或者对Android内存紧张的情况下需要被杀掉且不会立即重新创建这种行为也可接受的话,这是可以在onStartCommand()返回值中设置该值。例如在Service中定时从服务器中获取最新数据。
START_STICKY:表示Service运行的进程被Android系统强制杀掉之后,Android系统会将该Service依然设置为started状态(即运行状态),但是不再保存onStartCommand方法传入的intent对象,然后Android系统会尝试再次重新创建该Service,并执行onStartCommand()回调方法,这时onStartCommand()回调方法的Intent参数为null,也就是onStartCommand()方法虽然会执行但是获取不到intent信息。
使用场景:如果你的Service可以在任意时刻运行或结束都没什么问题,而且不需要intent信息,那么就可以在onStartCommand()方法中返回START_STICKY,比如一个用来播放背景音乐功能的Service就适合返回该值。
START_REDELIVER_INTENT:表示Service运行的进程被Android系统强制杀掉之后,与返回START_STICKY的情况类似,Android系统会将再次重新创建该Service,并执行onStartCommand()回调方法,但是不同的是,Android系统会再次将Service在被杀掉之前最后一次传入onStartCommand()方法中的Intent再次保留下来并再次传入到重新创建后的Service的onStartCommand方法中,这样我们就能读取到intent参数。
使用场景:如果我们的Service需要依赖具体的Intent才能运行(需要从Intent中读取相关数据信息等),并且在强制销毁后有必要重新创建运行,那么这样的Service就适合返回START_REDELIVER_INTENT。