Service基础:
Service与Activity同为四大组件之一, 与Activity不同的是Service是默默运行在后台的幕后英雄.开启一个Service之后你可以通过它在后台执行想要执行的任务, 比如网络连接, 播放音乐, 处理文件等操作.
Service默认开启在主线程中, 所以不能在Service中直接运行重量级操作.
Service有两种启动方式, 普通的StartedService,调用startService()方法启动, 启动之后不能再与启动它的组件进行通信. 还有加强版的BoundService, 调用bindService()方法启动, 启动之后可以保持与启动它的组件通信.
Service的子类必须实现其onBind()方法, 如果不希望Service被绑定, 那么该方法需要返回null.
StartedService:
通过startService()方法启动一个Service, 这种情况下Service不会返回结果给启动者. 可以在Service内部调用stopSelf()或者在Service外部调用stopService()来停止这个Service. 如果不调用这些方法, 那么Service将一直运行直到被系统回收, 即便启动它的Activity被销毁, 该Service也不会因此而被销毁.
启动一个StartedService三部曲:
1. 在Mainifest.xml文件中声明一个Service.
2. 继承Service类或者它的子类.
3. 在组件中调用startService()方法, 传入一个Intent参数.
在Service初次启动的时候, 会依次调用onCreate()方法和onStartCommand()方法. 如果调用startService()方法来启动一个正在运行中的Service, 那么会调用该Service的onStartCommand()方法, 而不会再调用onCreate().
BoundService:
其实BoundService应该算是StartedService的进阶, 因为我们可以通过调用bindService来启动一个新的Service, 也用它来绑定一个已经存在的Service. 当我们希望Activity或者其他组件需要与Service通信的时候, 我们应该用BoundService,
BoundService在实现上与StartService的不同之处:
1. 两者都需要实现onBind()方法, 但是返回值却不同, StartedService返回null, 而BoundService必须返回一个IBinder对象.
2. 通过bindService()启动的Service, 无需调用stopSelf()或者stopService()来结束, 当没有组件绑定该Service的时候, 它会被系统回收. 如果该Service是通过startService()启动的, 那么在该Service没有被绑定的时候, 依然需要调用stopSelf()或者stopService()来结束它.
BoundService与组件间的通信(同时也是IPC的部分重要内容, 另起文章):
前面提到了, BoundService和StartService区别就是是否可以在Service启动之后跟启动它的组件通信. 在了解通信之前, 先介绍一下bindService()的过程. APP组件(客户端)可以通过bindService()方法来绑定一个Service, 当被绑定时, Service会调用onBind()方法, 该方法返回一个IBinder对象给客户端. 绑定过程是异步的, 想要获取这个IBinder对象, 那么客户端需要创建一个ServiceConnection对象, 并在bindService()的时候作为参数传给它. ServiceConnection对象的回调方法onServiceConnected()中我们可以获取到这个IBinder对象. 另外在四大组件中, Broadcast receiver不能绑定Service. 绑定一个Service的步骤:
1. 创建一个ServiceConnection对象, 并且重写它的两个方法:
onServiceConnected(): 在Service的onBind()后调用, 用于返回IBinder对象.
onServiceDisconnected(): 在于Service失去连接之后调用, 比如Service挂了或者被系统回收了, 但是正常解除绑定的时候不会调用该方法.
2. 调用bindService()方法, 并将ServiceConnection对象作为参数传给它.
3. 系统调用onServiceConnected()方法.
4. 客户端调用unbindService()方法解除绑定.
那么BoundService是如何通信的呢? 主要通信方法有三种:
1. 当Service只是服务于APP内部, 并且与启动Service的组件之间没有跨进程的时候, 应该通过继承Binder类来实现. 实现方法是酱婶儿的:
a. 继承Binder类. 该类需要提供可以供组件调用的公共方法; 或者也可以带Service的实例, 以便调用Service的公共方法; 再或者其它的什么类, 总之得带个公共方法, 要不 然就没意义了.
b. 在onBind()中返回该类的一个实例.