一.概述
Service 作为四大组件之一,是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。Service不能和用户进行交互,不能自己启动,可以由Activity,BroadReceiver等其他应用组件启动,即使用户切换到其他应用,服务仍将在后台继续运行。
组件可以绑定到Service,以与之进行交互,甚至是执行进程间通信 (IPC)。
比如说一边听音乐一边做其他的事情,网络数据定时更新等等都需要Service一直在后台运行。
二.Service的生命周期和启动模式
Service有两种启动模式,通过startService()启动服务和通过bindService()绑定服务。
下图左边为startService()下的生命周期,右边为bindService()下的生命周期。
方法 | 方法说明 |
---|---|
onCreate() | 创建Service |
onStartService() | 请求启动Service |
onStartCommand() | 启动Service |
onBind() | 绑定Service |
onUnbind() | 解绑Service |
onDestroy() | 销毁Service |
1.通过startService()启动服务:
特点:
通过调用 startService() 启动服务(调用onStartCommand()),与调用者没有关系,服务将一直运行,直到服务使用 stopSelf() 自行停止运行,或由其他组件通过调用 stopService() 停止它为止。此时系统会调用onDestory()。
生命周期调用的方法:
这种启动模式下,首次启动服务时调用方法为onCreate()->onStartCommand(),如果服务已经启动再次调用只会触发onStartCommand()方法。
2.通过bindService()绑定服务:
特点:
通过调用 bindService() 来创建服务(且未调用 onStartCommand()),与调用者绑定.服务只会在该组件与其绑定时运行。一旦该服务与所有客户端之间的绑定全部取消,系统便会销毁它。
生命周期调用的方法:
这种启动模式下,首次启动服务时调用方法为onCreate()->onBind(),如果服务已经启动再次调用不会再触发这两个方法,调用者退出时系统会调用服务的onUnbind()->onDestory()。
想主动解除绑定可调用Contex.unbindService()方法,系统依次调用onUnbind()->onDestory()。
说明:
Service可以使用这两种启动方式任意一种或是同时使用这两种启动方式。
三.Service的基本使用
在清单文件中注册服务MyService:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
......
<service android:name=".MyService"/>
</application>
定义MyService继承Service,实现回调接口:
public class MyService extends Service {
private static final String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return null;
}
}
1.启动服务:
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
2.停止服务:
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
3.绑定服务:
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
其中bindService(intent, serviceConnection, BIND_AUTO_CREATE);方法的第二个参数是一个ServiceConnection对象。ServiceConnection代表与服务的连接,它有两个方法。
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.d(TAG, "onServiceConnected: ");
binder = (MyService.MyBinder) iBinder;
binder.test();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d(TAG, "onServiceDisconnected: ");
}
};
onServiceConnected:在操作者在连接一个服务成功时被调用。
onServiceDisconnected:在服务崩溃或被杀死导致的连接中断时被调用,而如果自己解除绑定时则不会被调用。
4.解除绑定服务:
unbindService(serviceConnection);
四.IntentServer
1.基本使用:
不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
需要构造函数和 onHandleIntent() 实现:
public class MyIntentService extends IntentService{
private static final String TAG = "MyIntentService";
public MyIntentService(){
super("superIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "onHandleIntent: ");
synchronized(this){
try {
wait(20*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return super.onBind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
}
2.特点:
(1)创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
(2)创建工作队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,这样就永远不必担心多线程问题。
(3)在处理完所有启动请求后停止服务,因此永远不必调用 stopSelf()。
提供 onBind() 的默认实现(返回 null)。
(4)提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。
3.原理:(创建一个工作线程来处理多线程任务)
(1)通过HandlerThread单独开启一个名为IntentService的线程。
(2)创建一个名叫ServiceHandler的内部Handler。
(3)把内部Handler与HandlerThread所对应的子线程进行绑定。
(4)通过onStartCommand()传递给服务intent,依次插入到工作队列中,并逐个发送给onHandleIntent()。
(5)通过onHandleIntent()来依次处理所有Intent请求对象所对应的任务。
4.说明:
(1)IntentService可以单独开启一个新的线程:
在onCreate()里面通过实例化HanderThread新建线程启动,所以不需要额外新建线程。
(2)不建议通过 bindService() 启动 IntentService:
IntentService 的 onBind() 默认返回 null,不适合 bindService() 启动服务。
采用bindService() 启动 IntentService不会调用onstart()或者onstartcommand()方法,所以不会将消息发送到消息队列,那么onHandleIntent()将不会回调,即无法实现多线程的操作,相当于在使用 Service 而不是 IntentService。
(3)多次启动IntentService工作任务顺序执行:
由于onCreate() 方法只会调用一次,所以只会创建一个工作线程;
当多次调用 startService(Intent) 时(onStartCommand也会调用多次)其实并不会创建新的工作线程,只是把消息加入消息队列中等待执行,所以,多次启动 IntentService 会按顺序执行事件
如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。
参考文档:
https://developer.android.com/guide/components/services.html#Lifecycle
http://www.jianshu.com/p/8a3c44a9173a